furi_hal_flash.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. #include <furi_hal_flash.h>
  2. #include <furi_hal_bt.h>
  3. #include <furi.h>
  4. #include <ble.h>
  5. #include <shci.h>
  6. #include <stm32wbxx.h>
  7. #define TAG "FuriHalFlash"
  8. #define FURI_HAL_CRITICAL_MSG "Critical flash operation fail"
  9. #define FURI_HAL_FLASH_READ_BLOCK 8
  10. #define FURI_HAL_FLASH_WRITE_BLOCK 8
  11. #define FURI_HAL_FLASH_PAGE_SIZE 4096
  12. #define FURI_HAL_FLASH_CYCLES_COUNT 10000
  13. #define FURI_HAL_FLASH_TIMEOUT 1000
  14. #define FURI_HAL_FLASH_KEY1 0x45670123U
  15. #define FURI_HAL_FLASH_KEY2 0xCDEF89ABU
  16. #define FURI_HAL_FLASH_TOTAL_PAGES 256
  17. #define FURI_HAL_FLASH_SR_ERRORS \
  18. (FLASH_SR_OPERR | FLASH_SR_PROGERR | FLASH_SR_WRPERR | FLASH_SR_PGAERR | FLASH_SR_SIZERR | \
  19. FLASH_SR_PGSERR | FLASH_SR_MISERR | FLASH_SR_FASTERR | FLASH_SR_RDERR | FLASH_SR_OPTVERR)
  20. //#define FURI_HAL_FLASH_OB_START_ADDRESS 0x1FFF8000
  21. #define FURI_HAL_FLASH_OPT_KEY1 0x08192A3B
  22. #define FURI_HAL_FLASH_OPT_KEY2 0x4C5D6E7F
  23. #define FURI_HAL_FLASH_OB_TOTAL_WORDS (0x80 / (sizeof(uint32_t) * 2))
  24. #define IS_ADDR_ALIGNED_64BITS(__VALUE__) (((__VALUE__)&0x7U) == (0x00UL))
  25. #define IS_FLASH_PROGRAM_ADDRESS(__VALUE__) \
  26. (((__VALUE__) >= FLASH_BASE) && ((__VALUE__) <= (FLASH_BASE + FLASH_SIZE - 8UL)) && \
  27. (((__VALUE__) % 8UL) == 0UL))
  28. /* Free flash space borders, exported by linker */
  29. extern const void __free_flash_start__;
  30. size_t furi_hal_flash_get_base() {
  31. return FLASH_BASE;
  32. }
  33. size_t furi_hal_flash_get_read_block_size() {
  34. return FURI_HAL_FLASH_READ_BLOCK;
  35. }
  36. size_t furi_hal_flash_get_write_block_size() {
  37. return FURI_HAL_FLASH_WRITE_BLOCK;
  38. }
  39. size_t furi_hal_flash_get_page_size() {
  40. return FURI_HAL_FLASH_PAGE_SIZE;
  41. }
  42. size_t furi_hal_flash_get_cycles_count() {
  43. return FURI_HAL_FLASH_CYCLES_COUNT;
  44. }
  45. const void* furi_hal_flash_get_free_start_address() {
  46. return &__free_flash_start__;
  47. }
  48. const void* furi_hal_flash_get_free_end_address() {
  49. uint32_t sfr_reg_val = READ_REG(FLASH->SFR);
  50. uint32_t sfsa = (READ_BIT(sfr_reg_val, FLASH_SFR_SFSA) >> FLASH_SFR_SFSA_Pos);
  51. return (const void*)((sfsa * FURI_HAL_FLASH_PAGE_SIZE) + FLASH_BASE);
  52. }
  53. size_t furi_hal_flash_get_free_page_start_address() {
  54. size_t start = (size_t)furi_hal_flash_get_free_start_address();
  55. size_t page_start = start - start % FURI_HAL_FLASH_PAGE_SIZE;
  56. if(page_start != start) {
  57. page_start += FURI_HAL_FLASH_PAGE_SIZE;
  58. }
  59. return page_start;
  60. }
  61. size_t furi_hal_flash_get_free_page_count() {
  62. size_t end = (size_t)furi_hal_flash_get_free_end_address();
  63. size_t page_start = (size_t)furi_hal_flash_get_free_page_start_address();
  64. return (end - page_start) / FURI_HAL_FLASH_PAGE_SIZE;
  65. }
  66. void furi_hal_flash_init() {
  67. // Errata 2.2.9, Flash OPTVERR flag is always set after system reset
  68. WRITE_REG(FLASH->SR, FLASH_SR_OPTVERR);
  69. //__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
  70. }
  71. static void furi_hal_flash_unlock() {
  72. /* verify Flash is locked */
  73. furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U);
  74. /* Authorize the FLASH Registers access */
  75. WRITE_REG(FLASH->KEYR, FURI_HAL_FLASH_KEY1);
  76. WRITE_REG(FLASH->KEYR, FURI_HAL_FLASH_KEY2);
  77. /* verify Flash is unlocked */
  78. furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) == 0U);
  79. }
  80. static void furi_hal_flash_lock(void) {
  81. /* verify Flash is unlocked */
  82. furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) == 0U);
  83. /* Set the LOCK Bit to lock the FLASH Registers access */
  84. /* @Note The lock and unlock procedure is done only using CR registers even from CPU2 */
  85. SET_BIT(FLASH->CR, FLASH_CR_LOCK);
  86. /* verify Flash is locked */
  87. furi_check(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0U);
  88. }
  89. static void furi_hal_flash_begin_with_core2(bool erase_flag) {
  90. // Take flash controller ownership
  91. while(LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID) != 0) {
  92. osThreadYield();
  93. }
  94. // Unlock flash operation
  95. furi_hal_flash_unlock();
  96. // Erase activity notification
  97. if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);
  98. // 64mHz 5us core2 flag protection
  99. for(volatile uint32_t i = 0; i < 35; i++)
  100. ;
  101. while(true) {
  102. // Wait till flash controller become usable
  103. while(LL_FLASH_IsActiveFlag_OperationSuspended()) {
  104. osThreadYield();
  105. };
  106. // Just a little more love
  107. taskENTER_CRITICAL();
  108. // Actually we already have mutex for it, but specification is specification
  109. if(LL_HSEM_IsSemaphoreLocked(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) {
  110. taskEXIT_CRITICAL();
  111. osThreadYield();
  112. continue;
  113. }
  114. // Take sempahopre and prevent core2 from anything funky
  115. if(LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != 0) {
  116. taskEXIT_CRITICAL();
  117. osThreadYield();
  118. continue;
  119. }
  120. break;
  121. }
  122. }
  123. static void furi_hal_flash_begin(bool erase_flag) {
  124. // Acquire dangerous ops mutex
  125. furi_hal_bt_lock_core2();
  126. // If Core2 is running use IPC locking
  127. if(furi_hal_bt_is_alive()) {
  128. furi_hal_flash_begin_with_core2(erase_flag);
  129. } else {
  130. furi_hal_flash_unlock();
  131. }
  132. }
  133. static void furi_hal_flash_end_with_core2(bool erase_flag) {
  134. // Funky ops are ok at this point
  135. LL_HSEM_ReleaseLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID, 0);
  136. // Task switching is ok
  137. taskEXIT_CRITICAL();
  138. // Doesn't make much sense, does it?
  139. while(READ_BIT(FLASH->SR, FLASH_SR_BSY)) {
  140. osThreadYield();
  141. }
  142. // Erase activity over, core2 can continue
  143. if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF);
  144. // Lock flash controller
  145. furi_hal_flash_lock();
  146. // Release flash controller ownership
  147. LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 0);
  148. }
  149. static void furi_hal_flash_end(bool erase_flag) {
  150. // If Core2 is running use IPC locking
  151. if(furi_hal_bt_is_alive()) {
  152. furi_hal_flash_end_with_core2(erase_flag);
  153. } else {
  154. furi_hal_flash_lock();
  155. }
  156. // Release dangerous ops mutex
  157. furi_hal_bt_unlock_core2();
  158. }
  159. static void furi_hal_flush_cache(void) {
  160. /* Flush instruction cache */
  161. if(READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) == FLASH_ACR_ICEN) {
  162. /* Disable instruction cache */
  163. LL_FLASH_DisableInstCache();
  164. /* Reset instruction cache */
  165. LL_FLASH_EnableInstCacheReset();
  166. LL_FLASH_DisableInstCacheReset();
  167. /* Enable instruction cache */
  168. LL_FLASH_EnableInstCache();
  169. }
  170. /* Flush data cache */
  171. if(READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) == FLASH_ACR_DCEN) {
  172. /* Disable data cache */
  173. LL_FLASH_DisableDataCache();
  174. /* Reset data cache */
  175. LL_FLASH_EnableDataCacheReset();
  176. LL_FLASH_DisableDataCacheReset();
  177. /* Enable data cache */
  178. LL_FLASH_EnableDataCache();
  179. }
  180. }
  181. bool furi_hal_flash_wait_last_operation(uint32_t timeout) {
  182. uint32_t error = 0;
  183. uint32_t countdown = 0;
  184. // Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
  185. // Even if the FLASH operation fails, the BUSY flag will be reset and an error
  186. // flag will be set
  187. countdown = timeout;
  188. while(READ_BIT(FLASH->SR, FLASH_SR_BSY)) {
  189. if(LL_SYSTICK_IsActiveCounterFlag()) {
  190. countdown--;
  191. }
  192. if(countdown == 0) {
  193. return false;
  194. }
  195. }
  196. /* Check FLASH operation error flags */
  197. error = FLASH->SR;
  198. /* Check FLASH End of Operation flag */
  199. if((error & FLASH_SR_EOP) != 0U) {
  200. /* Clear FLASH End of Operation pending bit */
  201. CLEAR_BIT(FLASH->SR, FLASH_SR_EOP);
  202. }
  203. /* Now update error variable to only error value */
  204. error &= FURI_HAL_FLASH_SR_ERRORS;
  205. furi_check(error == 0);
  206. /* clear error flags */
  207. CLEAR_BIT(FLASH->SR, error);
  208. /* Wait for control register to be written */
  209. countdown = timeout;
  210. while(READ_BIT(FLASH->SR, FLASH_SR_CFGBSY)) {
  211. if(LL_SYSTICK_IsActiveCounterFlag()) {
  212. countdown--;
  213. }
  214. if(countdown == 0) {
  215. return false;
  216. }
  217. }
  218. return true;
  219. }
  220. bool furi_hal_flash_erase(uint8_t page) {
  221. furi_hal_flash_begin(true);
  222. // Ensure that controller state is valid
  223. furi_check(FLASH->SR == 0);
  224. /* Verify that next operation can be proceed */
  225. furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
  226. /* Select page and start operation */
  227. MODIFY_REG(
  228. FLASH->CR, FLASH_CR_PNB, ((page << FLASH_CR_PNB_Pos) | FLASH_CR_PER | FLASH_CR_STRT));
  229. /* Wait for last operation to be completed */
  230. furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
  231. /* If operation is completed or interrupted, disable the Page Erase Bit */
  232. CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
  233. /* Flush the caches to be sure of the data consistency */
  234. furi_hal_flush_cache();
  235. furi_hal_flash_end(true);
  236. return true;
  237. }
  238. static inline bool furi_hal_flash_write_dword_internal(size_t address, uint64_t* data) {
  239. /* Program first word */
  240. *(uint32_t*)address = (uint32_t)*data;
  241. // Barrier to ensure programming is performed in 2 steps, in right order
  242. // (independently of compiler optimization behavior)
  243. __ISB();
  244. /* Program second word */
  245. *(uint32_t*)(address + 4U) = (uint32_t)(*data >> 32U);
  246. /* Wait for last operation to be completed */
  247. furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
  248. return true;
  249. }
  250. bool furi_hal_flash_write_dword(size_t address, uint64_t data) {
  251. furi_hal_flash_begin(false);
  252. // Ensure that controller state is valid
  253. furi_check(FLASH->SR == 0);
  254. /* Check the parameters */
  255. furi_check(IS_ADDR_ALIGNED_64BITS(address));
  256. furi_check(IS_FLASH_PROGRAM_ADDRESS(address));
  257. /* Set PG bit */
  258. SET_BIT(FLASH->CR, FLASH_CR_PG);
  259. /* Do the thing */
  260. furi_check(furi_hal_flash_write_dword_internal(address, &data));
  261. /* If the program operation is completed, disable the PG or FSTPG Bit */
  262. CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
  263. furi_hal_flash_end(false);
  264. /* Wait for last operation to be completed */
  265. furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
  266. return true;
  267. }
  268. static size_t furi_hal_flash_get_page_address(uint8_t page) {
  269. return furi_hal_flash_get_base() + page * FURI_HAL_FLASH_PAGE_SIZE;
  270. }
  271. bool furi_hal_flash_program_page(const uint8_t page, const uint8_t* data, uint16_t _length) {
  272. uint16_t length = _length;
  273. furi_check(length <= FURI_HAL_FLASH_PAGE_SIZE);
  274. furi_hal_flash_erase(page);
  275. furi_hal_flash_begin(false);
  276. // Ensure that controller state is valid
  277. furi_check(FLASH->SR == 0);
  278. size_t page_start_address = furi_hal_flash_get_page_address(page);
  279. /* Set PG bit */
  280. SET_BIT(FLASH->CR, FLASH_CR_PG);
  281. size_t i_dwords = 0;
  282. for(i_dwords = 0; i_dwords < (length / 8); ++i_dwords) {
  283. /* Do the thing */
  284. size_t data_offset = i_dwords * 8;
  285. furi_check(furi_hal_flash_write_dword_internal(
  286. page_start_address + data_offset, (uint64_t*)&data[data_offset]));
  287. }
  288. if((length % 8) != 0) {
  289. /* there are more bytes, not fitting into dwords */
  290. uint64_t tail_data = 0;
  291. size_t data_offset = i_dwords * 8;
  292. for(int32_t tail_i = 0; tail_i < (length % 8); ++tail_i) {
  293. tail_data |= (((uint64_t)data[data_offset + tail_i]) << (tail_i * 8));
  294. }
  295. furi_check(
  296. furi_hal_flash_write_dword_internal(page_start_address + data_offset, &tail_data));
  297. }
  298. /* If the program operation is completed, disable the PG or FSTPG Bit */
  299. CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
  300. furi_hal_flash_end(false);
  301. return true;
  302. }
  303. int16_t furi_hal_flash_get_page_number(size_t address) {
  304. const size_t flash_base = furi_hal_flash_get_base();
  305. if((address < flash_base) ||
  306. (address > flash_base + FURI_HAL_FLASH_TOTAL_PAGES * FURI_HAL_FLASH_PAGE_SIZE)) {
  307. return -1;
  308. }
  309. return (address - flash_base) / FURI_HAL_FLASH_PAGE_SIZE;
  310. }
  311. uint32_t furi_hal_flash_ob_get_word(size_t word_idx, bool complementary) {
  312. furi_check(word_idx <= FURI_HAL_FLASH_OB_TOTAL_WORDS);
  313. const uint32_t* ob_data = (const uint32_t*)(OPTION_BYTE_BASE);
  314. size_t raw_word_idx = word_idx * 2;
  315. if(complementary) {
  316. raw_word_idx += 1;
  317. }
  318. return ob_data[raw_word_idx];
  319. }
  320. void furi_hal_flash_ob_unlock() {
  321. furi_check(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0U);
  322. furi_hal_flash_begin(true);
  323. WRITE_REG(FLASH->OPTKEYR, FURI_HAL_FLASH_OPT_KEY1);
  324. __ISB();
  325. WRITE_REG(FLASH->OPTKEYR, FURI_HAL_FLASH_OPT_KEY2);
  326. /* verify OB area is unlocked */
  327. furi_check(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == 0U);
  328. }
  329. void furi_hal_flash_ob_lock() {
  330. furi_check(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) == 0U);
  331. SET_BIT(FLASH->CR, FLASH_CR_OPTLOCK);
  332. furi_hal_flash_end(true);
  333. furi_check(READ_BIT(FLASH->CR, FLASH_CR_OPTLOCK) != 0U);
  334. }
  335. typedef enum {
  336. FuriHalFlashObInvalid,
  337. FuriHalFlashObRegisterUserRead,
  338. FuriHalFlashObRegisterPCROP1AStart,
  339. FuriHalFlashObRegisterPCROP1AEnd,
  340. FuriHalFlashObRegisterWRPA,
  341. FuriHalFlashObRegisterWRPB,
  342. FuriHalFlashObRegisterPCROP1BStart,
  343. FuriHalFlashObRegisterPCROP1BEnd,
  344. FuriHalFlashObRegisterIPCCMail,
  345. FuriHalFlashObRegisterSecureFlash,
  346. FuriHalFlashObRegisterC2Opts,
  347. } FuriHalFlashObRegister;
  348. typedef struct {
  349. FuriHalFlashObRegister ob_reg;
  350. uint32_t* ob_register_address;
  351. } FuriHalFlashObMapping;
  352. #define OB_REG_DEF(INDEX, REG) \
  353. { .ob_reg = INDEX, .ob_register_address = (uint32_t*)(REG) }
  354. static const FuriHalFlashObMapping furi_hal_flash_ob_reg_map[FURI_HAL_FLASH_OB_TOTAL_WORDS] = {
  355. OB_REG_DEF(FuriHalFlashObRegisterUserRead, (&FLASH->OPTR)),
  356. OB_REG_DEF(FuriHalFlashObRegisterPCROP1AStart, (&FLASH->PCROP1ASR)),
  357. OB_REG_DEF(FuriHalFlashObRegisterPCROP1AEnd, (&FLASH->PCROP1AER)),
  358. OB_REG_DEF(FuriHalFlashObRegisterWRPA, (&FLASH->WRP1AR)),
  359. OB_REG_DEF(FuriHalFlashObRegisterWRPB, (&FLASH->WRP1BR)),
  360. OB_REG_DEF(FuriHalFlashObRegisterPCROP1BStart, (&FLASH->PCROP1BSR)),
  361. OB_REG_DEF(FuriHalFlashObRegisterPCROP1BEnd, (&FLASH->PCROP1BER)),
  362. OB_REG_DEF(FuriHalFlashObInvalid, (NULL)),
  363. OB_REG_DEF(FuriHalFlashObInvalid, (NULL)),
  364. OB_REG_DEF(FuriHalFlashObInvalid, (NULL)),
  365. OB_REG_DEF(FuriHalFlashObInvalid, (NULL)),
  366. OB_REG_DEF(FuriHalFlashObInvalid, (NULL)),
  367. OB_REG_DEF(FuriHalFlashObInvalid, (NULL)),
  368. OB_REG_DEF(FuriHalFlashObRegisterIPCCMail, (NULL)),
  369. OB_REG_DEF(FuriHalFlashObRegisterSecureFlash, (NULL)),
  370. OB_REG_DEF(FuriHalFlashObRegisterC2Opts, (NULL)),
  371. };
  372. void furi_hal_flash_ob_apply() {
  373. furi_hal_flash_ob_unlock();
  374. /* OBL_LAUNCH: When set to 1, this bit forces the option byte reloading.
  375. * It cannot be written if OPTLOCK is set */
  376. SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
  377. furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
  378. furi_hal_flash_ob_lock();
  379. }
  380. bool furi_hal_flash_ob_set_word(size_t word_idx, const uint32_t value) {
  381. furi_check(word_idx < FURI_HAL_FLASH_OB_TOTAL_WORDS);
  382. const FuriHalFlashObMapping* reg_def = &furi_hal_flash_ob_reg_map[word_idx];
  383. if(reg_def->ob_register_address == NULL) {
  384. FURI_LOG_E(TAG, "Attempt to set RO OB word %d", word_idx);
  385. return false;
  386. }
  387. FURI_LOG_W(
  388. TAG,
  389. "Setting OB reg %d for word %d (addr 0x%08X) to 0x%08X",
  390. reg_def->ob_reg,
  391. word_idx,
  392. reg_def->ob_register_address,
  393. value);
  394. /* 1. Clear OPTLOCK option lock bit with the clearing sequence */
  395. furi_hal_flash_ob_unlock();
  396. /* 2. Write the desired options value in the options registers */
  397. *reg_def->ob_register_address = value;
  398. /* 3. Check that no Flash memory operation is on going by checking the BSY && PESD */
  399. furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
  400. while(LL_FLASH_IsActiveFlag_OperationSuspended()) {
  401. osThreadYield();
  402. };
  403. /* 4. Set the Options start bit OPTSTRT */
  404. SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);
  405. /* 5. Wait for the BSY bit to be cleared. */
  406. furi_check(furi_hal_flash_wait_last_operation(FURI_HAL_FLASH_TIMEOUT));
  407. furi_hal_flash_ob_lock();
  408. return true;
  409. }
  410. const FuriHalFlashRawOptionByteData* furi_hal_flash_ob_get_raw_ptr() {
  411. return (const FuriHalFlashRawOptionByteData*)OPTION_BYTE_BASE;
  412. }