drv_flash_f4.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * Copyright (C) 2022-2024, Xiaohua Semiconductor Co., Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-04-28 CDT first version
  9. */
  10. #include "board.h"
  11. #if defined(BSP_USING_ON_CHIP_FLASH)
  12. #include "drv_config.h"
  13. #include "drv_flash.h"
  14. #if defined(RT_USING_FAL)
  15. #include "fal.h"
  16. #endif
  17. //#define DRV_DEBUG
  18. #define LOG_TAG "drv.flash"
  19. #include <drv_log.h>
  20. /**
  21. * @brief Gets the sector number.
  22. * @param addr flash address
  23. * @param size erase bytes size
  24. * @retval Sector number.
  25. */
  26. static rt_uint32_t GetSectorNum(rt_uint32_t addr, size_t size)
  27. {
  28. rt_uint32_t firstSector = 0, lastSector = 0;
  29. rt_uint32_t temp = 0;
  30. rt_uint32_t NumOfSectors = 0;
  31. firstSector = addr / SECTOR_SIZE;
  32. temp = addr + size;
  33. lastSector = temp / SECTOR_SIZE;
  34. if (0U != (temp % SECTOR_SIZE))
  35. {
  36. lastSector += 1U;
  37. }
  38. NumOfSectors = lastSector - firstSector + 1U;
  39. return NumOfSectors;
  40. }
  41. /**
  42. * @brief Read data from flash.
  43. * @param addr flash address
  44. * @param buf buffer to store read data
  45. * @param size read bytes size
  46. * @return result
  47. */
  48. int hc32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size)
  49. {
  50. if ((addr + size) > HC32_FLASH_END_ADDRESS)
  51. {
  52. LOG_E("read outrange flash size! addr is (0x%p)", (void *)(addr + size));
  53. return -1;
  54. }
  55. if (LL_OK != EFM_ReadByte(addr, buf, size))
  56. {
  57. return -RT_ERROR;
  58. }
  59. return size;
  60. }
  61. /**
  62. * @brief Write data to flash.
  63. * @param addr flash address
  64. * @param buf the write data buffer
  65. * @param size write bytes size
  66. * @return result
  67. * @note This operation's units is word.
  68. * @note This operation must after erase.
  69. */
  70. int hc32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size)
  71. {
  72. uint8_t u8MemBuf[4] = {0xFF, 0xFF, 0xFF, 0xFF};
  73. rt_err_t result = RT_EOK;
  74. rt_uint32_t newAddr = addr, offsetVal = 0;
  75. rt_uint32_t index = 0, u32Cnt = 0;
  76. #if defined (HC32F4A0) || defined (HC32F472) || defined (HC32F448)
  77. rt_uint32_t FirstSector = 0, NumOfSectors = 0;
  78. #endif
  79. if ((addr + size) > HC32_FLASH_END_ADDRESS)
  80. {
  81. LOG_E("write outrange flash size! addr is (0x%p)", (void *)(addr + size));
  82. return -RT_EINVAL;
  83. }
  84. if (size < 1)
  85. {
  86. return -RT_EINVAL;
  87. }
  88. /* EFM_FWMC write enable */
  89. EFM_FWMC_Cmd(ENABLE);
  90. #if defined (HC32F4A0) || defined (HC32F472) || defined (HC32F448)
  91. /* calculate sector information */
  92. FirstSector = addr / SECTOR_SIZE,
  93. NumOfSectors = GetSectorNum(addr, size);
  94. /* Sectors disable write protection */
  95. EFM_SequenceSectorOperateCmd(FirstSector, NumOfSectors, ENABLE);
  96. #endif
  97. /* Word align */
  98. if (0U != (addr % 4))
  99. {
  100. newAddr = (addr / 4 + 1U) * 4;
  101. offsetVal = newAddr - addr;
  102. if (offsetVal >= size)
  103. {
  104. result = -RT_ERROR;
  105. index = 4 - offsetVal;
  106. if (LL_OK == EFM_ReadByte(newAddr - 4, u8MemBuf, index))
  107. {
  108. for (u32Cnt = 0; u32Cnt < size; u32Cnt++)
  109. {
  110. u8MemBuf[index + u32Cnt] = buf[u32Cnt];
  111. }
  112. /* program */
  113. if (LL_OK == EFM_Program(newAddr - 4, u8MemBuf, 4))
  114. {
  115. result = RT_EOK;
  116. }
  117. }
  118. goto __exit;
  119. }
  120. else
  121. {
  122. size = size - offsetVal;
  123. }
  124. }
  125. /* program */
  126. if (LL_OK != EFM_Program(newAddr, (uint8_t *)&buf[offsetVal], size))
  127. {
  128. result = -RT_ERROR;
  129. goto __exit;
  130. }
  131. __exit:
  132. #if defined (HC32F4A0) || defined (HC32F472) || defined (HC32F448)
  133. /* Sectors enable write protection */
  134. EFM_SequenceSectorOperateCmd(FirstSector, NumOfSectors, DISABLE);
  135. #endif
  136. EFM_FWMC_Cmd(DISABLE);
  137. if (result != RT_EOK)
  138. {
  139. return result;
  140. }
  141. return size;
  142. }
  143. /**
  144. * @brief Erase data on flash.
  145. * @param addr flash address
  146. * @param size erase bytes size
  147. * @return result
  148. * @note This operation is irreversible.
  149. */
  150. int hc32_flash_erase(rt_uint32_t addr, size_t size)
  151. {
  152. rt_err_t result = RT_EOK;
  153. rt_uint32_t NumOfSectors = 0;
  154. rt_uint32_t SectorVal = 0, u32Addr = addr;
  155. #if defined (HC32F4A0) || defined (HC32F472) || defined (HC32F448)
  156. rt_uint32_t FirstSector = 0;
  157. #endif
  158. if ((addr + size) > HC32_FLASH_END_ADDRESS)
  159. {
  160. LOG_E("ERROR: erase outrange flash size! addr is (0x%p)\n", (void *)(addr + size));
  161. return -RT_EINVAL;
  162. }
  163. if (size < 1)
  164. {
  165. return -RT_EINVAL;
  166. }
  167. /* EFM_FWMC write enable */
  168. EFM_FWMC_Cmd(ENABLE);
  169. /* calculate sector information */
  170. NumOfSectors = GetSectorNum(addr, size);
  171. #if defined (HC32F4A0) || defined (HC32F472) || defined (HC32F448)
  172. FirstSector = addr / SECTOR_SIZE,
  173. /* Sectors disable write protection */
  174. EFM_SequenceSectorOperateCmd(FirstSector, NumOfSectors, ENABLE);
  175. #endif
  176. /* Erase sector */
  177. for (SectorVal = 0U; SectorVal < NumOfSectors; SectorVal++)
  178. {
  179. if (LL_OK != EFM_SectorErase(u32Addr))
  180. {
  181. result = -RT_ERROR;
  182. break;
  183. }
  184. u32Addr += SECTOR_SIZE;
  185. }
  186. #if defined (HC32F4A0) || defined (HC32F472) || defined (HC32F448)
  187. /* Sectors enable write protection */
  188. EFM_SequenceSectorOperateCmd(FirstSector, NumOfSectors, DISABLE);
  189. #endif
  190. EFM_FWMC_Cmd(DISABLE);
  191. if (result != RT_EOK)
  192. {
  193. return result;
  194. }
  195. LOG_D("erase done: addr (0x%p), size %d", (void *)addr, size);
  196. return size;
  197. }
  198. #if defined(RT_USING_FAL)
  199. static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size);
  200. static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size);
  201. static int fal_flash_erase(long offset, size_t size);
  202. const struct fal_flash_dev hc32_onchip_flash =
  203. {
  204. .name = "onchip_flash",
  205. .addr = HC32_FLASH_START_ADDRESS,
  206. .len = HC32_FLASH_SIZE,
  207. .blk_size = HC32_FLASH_SIZE_GRANULARITY,
  208. .ops = {NULL, fal_flash_read, fal_flash_write, fal_flash_erase},
  209. .write_gran = 4
  210. };
  211. static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size)
  212. {
  213. return hc32_flash_read(hc32_onchip_flash.addr + offset, buf, size);
  214. }
  215. static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size)
  216. {
  217. return hc32_flash_write(hc32_onchip_flash.addr + offset, buf, size);
  218. }
  219. static int fal_flash_erase(long offset, size_t size)
  220. {
  221. return hc32_flash_erase(hc32_onchip_flash.addr + offset, size);
  222. }
  223. #endif
  224. #endif /* BSP_USING_ON_CHIP_FLASH */