drv_flash.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-05-20 Chasel first version
  9. *
  10. */
  11. #include <rtconfig.h>
  12. #include <rtdef.h>
  13. #ifdef BSP_USING_ON_CHIP_FLASH
  14. #include "drv_flash.h"
  15. #include <board.h>
  16. #if defined(RT_USING_FAL)
  17. #include "fal.h"
  18. #endif
  19. #define DRV_DEBUG
  20. #define LOG_TAG "drv.flash"
  21. #include <drv_log.h>
  22. #define FLASH_PAGE_SIZE 4096
  23. /* @note If there is no down-frequency processing, the timeout time needs to be modified */
  24. #ifdef ProgramTimeout
  25. #undef ProgramTimeout
  26. #define ProgramTimeout ((uint32_t)0x00010000)
  27. #endif
  28. /**
  29. * @brief Gets the page of a given address
  30. * @param Addr: Address of the FLASH Memory
  31. * @retval The page of a given address
  32. */
  33. static uint32_t GetPage(uint32_t addr)
  34. {
  35. uint32_t page = 0;
  36. page = RT_ALIGN_DOWN(addr, FLASH_PAGE_SIZE);
  37. return page;
  38. }
  39. /**
  40. * Read data from flash.
  41. * @note This operation's units is word.
  42. *
  43. * @param addr flash address
  44. * @param buf buffer to store read data
  45. * @param size read bytes size
  46. *
  47. * @return result
  48. */
  49. int ch32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size)
  50. {
  51. size_t i;
  52. if ((addr + size) > CH32_FLASH_END_ADDRESS)
  53. {
  54. LOG_E("read outrange flash size! addr is (0x%p)", (void *)(addr + size));
  55. return -RT_EINVAL;
  56. }
  57. for (i = 0; i < size; i++, buf++, addr++)
  58. {
  59. *buf = *(rt_uint8_t *) addr;
  60. }
  61. return size;
  62. }
  63. /**
  64. * Write data to flash.
  65. * @note This operation's units is word.
  66. * @note This operation must after erase. @see flash_erase.
  67. *
  68. * @param addr flash address
  69. * @param buf the write data buffer
  70. * @param size write bytes size
  71. *
  72. * @return result
  73. */
  74. int ch32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size)
  75. {
  76. rt_err_t result = RT_EOK;
  77. FLASH_Status status = 0;
  78. rt_uint32_t end_addr = addr + size;
  79. if (addr % 4 != 0)
  80. {
  81. LOG_E("write addr must be 4-byte alignment");
  82. return -RT_EINVAL;
  83. }
  84. if ((end_addr) > CH32_FLASH_END_ADDRESS)
  85. {
  86. LOG_E("write outrange flash size! addr is (0x%p)", (void *)(addr + size));
  87. return -RT_EINVAL;
  88. }
  89. if (((addr & 0x000000FF) == 0) && (size & 0xFFFFFF00)) {
  90. rt_uint32_t fast_size = (size & 0xFFFFFF00);
  91. status = FLASH_ROM_WRITE(addr, (rt_uint32_t *)buf, fast_size);
  92. if (status != FLASH_COMPLETE) {
  93. LOG_E("FLASH ROM Write Fail\r\n");
  94. return -RT_ERROR;
  95. }
  96. addr += fast_size;
  97. buf += fast_size;
  98. }
  99. if (addr == end_addr) {
  100. return size;
  101. }
  102. FLASH_Access_Clock_Cfg(FLASH_Access_SYSTEM_HALF);
  103. FLASH_Unlock();
  104. FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
  105. while (addr < end_addr)
  106. {
  107. status = FLASH_ProgramWord(addr, *((rt_uint32_t *)buf));
  108. if (status == FLASH_COMPLETE)
  109. {
  110. if (*(rt_uint32_t *)addr != *(rt_uint32_t *)buf)
  111. {
  112. result = -RT_ERROR;
  113. break;
  114. }
  115. addr += 4;
  116. buf += 4;
  117. }
  118. else
  119. {
  120. result = -RT_ERROR;
  121. break;
  122. }
  123. }
  124. FLASH_Lock();
  125. FLASH_Access_Clock_Cfg(FLASH_Access_SYSTEM);
  126. if (result != RT_EOK)
  127. {
  128. return result;
  129. }
  130. return size;
  131. }
  132. /**
  133. * Erase data on flash .
  134. * @note This operation is irreversible.
  135. * @note This operation's units is different which on many chips.
  136. *
  137. * @param addr flash address
  138. * @param size erase bytes size
  139. *
  140. * @return result
  141. */
  142. int ch32_flash_erase(rt_uint32_t addr, size_t size)
  143. {
  144. rt_err_t result = RT_EOK;
  145. FLASH_Status status = 0;
  146. uint32_t num_page = 0;
  147. uint32_t i = 0;
  148. rt_uint32_t total_size = size;
  149. if ((addr + size) > CH32_FLASH_END_ADDRESS)
  150. {
  151. LOG_E("ERROR: erase outrange flash size! addr is (0x%p)\n", (void *)(addr + size));
  152. return -RT_EINVAL;
  153. }
  154. if (((addr & 0x000000FF) == 0) && (total_size & 0xFFFFFF00)) {
  155. rt_uint32_t fast_size = (total_size & 0xFFFFFF00);
  156. status = FLASH_ROM_ERASE(addr, fast_size);
  157. if (status != FLASH_COMPLETE) {
  158. LOG_E("FLASH ROM Erase Fail\r\n");
  159. return -RT_ERROR;
  160. }
  161. addr += fast_size;
  162. total_size -= fast_size;
  163. }
  164. if (0 == total_size) {
  165. return size;
  166. }
  167. FLASH_Access_Clock_Cfg(FLASH_Access_SYSTEM_HALF);
  168. FLASH_Unlock();
  169. FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
  170. num_page = (total_size + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE;
  171. FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_WRPRTERR);
  172. for(i = 0; (i < num_page) && (status == FLASH_COMPLETE); i++)
  173. {
  174. status = FLASH_ErasePage(GetPage(addr + i * FLASH_PAGE_SIZE)); //Erase 4KB
  175. if(status != FLASH_COMPLETE)
  176. {
  177. LOG_E("FLASH Erase Fail\r\n");
  178. result = -RT_ERROR;
  179. goto __exit;
  180. }
  181. }
  182. __exit:
  183. FLASH_Lock();
  184. FLASH_Access_Clock_Cfg(FLASH_Access_SYSTEM);
  185. if (result != RT_EOK)
  186. {
  187. return -RT_ERROR;
  188. }
  189. return size;
  190. }
  191. #if defined(RT_USING_FAL)
  192. static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size);
  193. static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size);
  194. static int fal_flash_erase(long offset, size_t size);
  195. const struct fal_flash_dev ch32_onchip_flash = { "onchip_flash", CH32_FLASH_START_ADRESS, CH32_FLASH_SIZE, FLASH_PAGE_SIZE, {NULL, fal_flash_read, fal_flash_write, fal_flash_erase}, 8, {} ,};
  196. static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size)
  197. {
  198. return ch32_flash_read(ch32_onchip_flash.addr + offset, buf, size);
  199. }
  200. static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size)
  201. {
  202. return ch32_flash_write(ch32_onchip_flash.addr + offset, buf, size);
  203. }
  204. static int fal_flash_erase(long offset, size_t size)
  205. {
  206. return ch32_flash_erase(ch32_onchip_flash.addr + offset, size);
  207. }
  208. #endif
  209. #endif /* BSP_USING_ON_CHIP_FLASH */