furi-hal-flash.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include <furi-hal-flash.h>
  2. #include <furi-hal-bt.h>
  3. #include <furi.h>
  4. #include <stm32wbxx.h>
  5. /* Free flash space borders, exported by linker */
  6. extern const void __free_flash_start__;
  7. #define FURI_HAL_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. size_t furi_hal_flash_get_base() {
  14. return FLASH_BASE;
  15. }
  16. size_t furi_hal_flash_get_read_block_size() {
  17. return FURI_HAL_FLASH_READ_BLOCK;
  18. }
  19. size_t furi_hal_flash_get_write_block_size() {
  20. return FURI_HAL_FLASH_WRITE_BLOCK;
  21. }
  22. size_t furi_hal_flash_get_page_size() {
  23. return FURI_HAL_FLASH_PAGE_SIZE;
  24. }
  25. size_t furi_hal_flash_get_cycles_count() {
  26. return FURI_HAL_FLASH_CYCLES_COUNT;
  27. }
  28. const void* furi_hal_flash_get_free_start_address() {
  29. return &__free_flash_start__;
  30. }
  31. const void* furi_hal_flash_get_free_end_address() {
  32. FLASH_OBProgramInitTypeDef pOBInit;
  33. HAL_FLASHEx_OBGetConfig(&pOBInit);
  34. return (const void *)pOBInit.SecureFlashStartAddr;
  35. }
  36. size_t furi_hal_flash_get_free_page_start_address() {
  37. size_t start = (size_t)furi_hal_flash_get_free_start_address();
  38. size_t page_start = start - start % FURI_HAL_FLASH_PAGE_SIZE;
  39. if (page_start != start) {
  40. page_start += FURI_HAL_FLASH_PAGE_SIZE;
  41. }
  42. return page_start;
  43. }
  44. size_t furi_hal_flash_get_free_page_count() {
  45. size_t end = (size_t)furi_hal_flash_get_free_end_address();
  46. size_t page_start = (size_t)furi_hal_flash_get_free_page_start_address();
  47. return (end-page_start) / FURI_HAL_FLASH_PAGE_SIZE;
  48. }
  49. bool furi_hal_flash_erase(uint8_t page, uint8_t count) {
  50. furi_hal_bt_lock_flash(true);
  51. FLASH_EraseInitTypeDef erase;
  52. erase.TypeErase = FLASH_TYPEERASE_PAGES;
  53. erase.Page = page;
  54. erase.NbPages = count;
  55. uint32_t error_page = 0;
  56. HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase, &error_page);
  57. if (status != HAL_OK) {
  58. FURI_LOG_E(FURI_HAL_TAG, "Erase failed, ret: %d, page: %d", status, error_page);
  59. furi_crash(FURI_HAL_CRITICAL_MSG);
  60. }
  61. furi_hal_bt_unlock_flash(true);
  62. return true;
  63. }
  64. bool furi_hal_flash_write_dword(size_t address, uint64_t data) {
  65. furi_hal_bt_lock_flash(false);
  66. HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data);
  67. if (status != HAL_OK) {
  68. FURI_LOG_E(FURI_HAL_TAG, "Programming failed, ret: %d, address: %p", status, address);
  69. furi_crash(FURI_HAL_CRITICAL_MSG);
  70. }
  71. furi_hal_bt_unlock_flash(false);
  72. return true;
  73. }
  74. bool furi_hal_flash_write_row(size_t address, size_t source_address) {
  75. furi_hal_bt_lock_flash(false);
  76. HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, address, source_address);
  77. furi_check(status == HAL_OK);
  78. furi_hal_bt_unlock_flash(false);
  79. return true;
  80. }