drv_fmc.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /**************************************************************************//**
  2. *
  3. * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Change Logs:
  8. * Date Author Notes
  9. * 2020-3-03 FYChou First version
  10. *
  11. ******************************************************************************/
  12. #include <rtconfig.h>
  13. #if defined(BSP_USING_FMC)
  14. #include <rtdevice.h>
  15. #include "NuMicro.h"
  16. #if defined(PKG_USING_FAL)
  17. #include <fal.h>
  18. #endif
  19. /* Private define ---------------------------------------------------------------*/
  20. #define NU_GETBYTE_OFST(addr) (((addr)&0x3)*8)
  21. #define NU_GET_WALIGN(addr) ((addr)&~0x3)
  22. #define NU_GET_LSB2BIT(addr) ((addr)&0x3)
  23. /* Private typedef --------------------------------------------------------------*/
  24. /* Private functions ------------------------------------------------------------*/
  25. static int nu_fmc_init(void);
  26. #if defined(PKG_USING_FAL)
  27. static int aprom_read(long offset, uint8_t *buf, size_t size);
  28. static int aprom_write(long offset, const uint8_t *buf, size_t size);
  29. static int aprom_erase(long offset, size_t size);
  30. static int ldrom_read(long offset, uint8_t *buf, size_t size);
  31. static int ldrom_write(long offset, const uint8_t *buf, size_t size);
  32. static int ldrom_erase(long offset, size_t size);
  33. #endif /* PKG_USING_FAL */
  34. /* Public functions -------------------------------------------------------------*/
  35. int nu_fmc_read(long offset, uint8_t *buf, size_t size);
  36. int nu_fmc_write(long offset, const uint8_t *buf, size_t size);
  37. int nu_fmc_erase(long offset, size_t size);
  38. /* Private variables ------------------------------------------------------------*/
  39. static rt_mutex_t g_mutex_fmc = RT_NULL;
  40. /* Public variables -------------------------------------------------------------*/
  41. #if defined(PKG_USING_FAL)
  42. const struct fal_flash_dev Onchip_aprom_flash = { "OnChip_APROM", FMC_APROM_BASE, FMC_APROM_END, FMC_FLASH_PAGE_SIZE, {NULL, aprom_read, aprom_write, aprom_erase} };
  43. const struct fal_flash_dev Onchip_ldrom_flash = { "OnChip_LDROM", FMC_LDROM_BASE, FMC_LDROM_END, FMC_FLASH_PAGE_SIZE, {NULL, ldrom_read, ldrom_write, ldrom_erase} };
  44. #endif /* PKG_USING_FAL */
  45. int nu_fmc_read(long addr, uint8_t *buf, size_t size)
  46. {
  47. size_t read_size = 0;
  48. uint32_t addr_end = addr + size;
  49. uint32_t isp_rdata = 0;
  50. rt_mutex_take(g_mutex_fmc, RT_WAITING_FOREVER);
  51. SYS_UnlockReg();
  52. if (NU_GET_LSB2BIT(addr))
  53. isp_rdata = FMC_Read(NU_GET_WALIGN(addr));
  54. for (; addr < addr_end ;)
  55. {
  56. if (NU_GET_LSB2BIT(addr) == 0)
  57. {
  58. isp_rdata = FMC_Read(addr);
  59. if (addr_end - addr >= 4)
  60. {
  61. *(uint32_t *)buf = isp_rdata;
  62. addr += 4;
  63. buf += 4;
  64. read_size += 4;
  65. continue;
  66. }
  67. }
  68. *buf = isp_rdata >> NU_GETBYTE_OFST(addr);
  69. addr++;
  70. buf++;
  71. read_size++;
  72. }
  73. SYS_LockReg();
  74. rt_mutex_release(g_mutex_fmc);
  75. return read_size;
  76. }
  77. int nu_fmc_write(long addr, const uint8_t *buf, size_t size)
  78. {
  79. size_t write_size = 0;
  80. uint32_t addr_end = addr + size;
  81. uint32_t isp_rdata = 0;
  82. rt_mutex_take(g_mutex_fmc, RT_WAITING_FOREVER);
  83. SYS_UnlockReg();
  84. if (addr < FMC_APROM_END)
  85. FMC_ENABLE_AP_UPDATE();
  86. else if ((addr < FMC_LDROM_END) && addr >= FMC_LDROM_BASE)
  87. FMC_ENABLE_LD_UPDATE();
  88. else
  89. {
  90. goto Exit2;
  91. }
  92. if (NU_GET_LSB2BIT(addr))
  93. isp_rdata = FMC_Read(NU_GET_WALIGN(addr));
  94. for (; addr < addr_end ;)
  95. {
  96. if (addr_end - addr >= 4 && NU_GET_LSB2BIT(addr) == 0)
  97. {
  98. FMC_Write(addr, *((uint32_t *)buf));
  99. addr += 4;
  100. buf += 4;
  101. write_size += 4;
  102. continue;
  103. }
  104. if ((NU_GET_LSB2BIT(addr)) == 0x0)
  105. isp_rdata = FMC_Read(NU_GET_WALIGN(addr));
  106. isp_rdata = (isp_rdata & ~(0xFF << NU_GETBYTE_OFST(addr))) | ((*buf) << NU_GETBYTE_OFST(addr));
  107. if ((NU_GET_LSB2BIT(addr)) == 0x3)
  108. FMC_Write(NU_GET_WALIGN(addr), isp_rdata);
  109. addr++;
  110. buf++;
  111. write_size++;
  112. }
  113. if (NU_GET_LSB2BIT(addr))
  114. FMC_Write(NU_GET_WALIGN(addr), isp_rdata);
  115. FMC_DISABLE_AP_UPDATE();
  116. FMC_DISABLE_LD_UPDATE();
  117. Exit2:
  118. SYS_LockReg();
  119. rt_mutex_release(g_mutex_fmc);
  120. return write_size;
  121. }
  122. int nu_fmc_erase(long addr, size_t size)
  123. {
  124. size_t erased_size = 0;
  125. uint32_t addrptr;
  126. uint32_t addr_end = addr + size;
  127. #if defined(NU_SUPPORT_NONALIGN)
  128. uint8_t *page_sdtemp = RT_NULL;
  129. uint8_t *page_edtemp = RT_NULL;
  130. addrptr = addr & (FMC_FLASH_PAGE_SIZE - 1);
  131. if (addrptr)
  132. {
  133. page_sdtemp = rt_malloc(addrptr);
  134. if (page_sdtemp == RT_NULL)
  135. {
  136. erased_size = 0;
  137. goto Exit3;
  138. }
  139. if (nu_fmc_read(addr & ~(FMC_FLASH_PAGE_SIZE - 1), page_sdtemp, addrptr) != addrptr)
  140. {
  141. erased_size = 0;
  142. goto Exit3;
  143. }
  144. }
  145. addrptr = addr_end & (FMC_FLASH_PAGE_SIZE - 1);
  146. if (addrptr)
  147. {
  148. page_edtemp = rt_malloc(FMC_FLASH_PAGE_SIZE - addrptr);
  149. if (page_edtemp == RT_NULL)
  150. {
  151. erased_size = 0;
  152. goto Exit3;
  153. }
  154. if (nu_fmc_read(addr_end, page_edtemp, FMC_FLASH_PAGE_SIZE - addrptr) != FMC_FLASH_PAGE_SIZE - addrptr)
  155. {
  156. erased_size = 0;
  157. goto Exit3;
  158. }
  159. }
  160. #endif
  161. rt_mutex_take(g_mutex_fmc, RT_WAITING_FOREVER);
  162. SYS_UnlockReg();
  163. if (addr <= FMC_APROM_END)
  164. FMC_ENABLE_AP_UPDATE();
  165. else if ((addr < FMC_LDROM_END) && addr >= FMC_LDROM_BASE)
  166. FMC_ENABLE_LD_UPDATE();
  167. else
  168. {
  169. goto Exit2;
  170. }
  171. addrptr = (addr & ~(FMC_FLASH_PAGE_SIZE - 1));
  172. while (addrptr < addr_end)
  173. {
  174. if (FMC_Erase(addrptr) != RT_EOK)
  175. {
  176. goto Exit1;
  177. }
  178. erased_size += FMC_FLASH_PAGE_SIZE;
  179. addrptr += FMC_FLASH_PAGE_SIZE;
  180. }
  181. Exit1:
  182. FMC_DISABLE_AP_UPDATE();
  183. FMC_DISABLE_LD_UPDATE();
  184. Exit2:
  185. SYS_LockReg();
  186. rt_mutex_release(g_mutex_fmc);
  187. #if defined(NU_SUPPORT_NONALIGN)
  188. if (erased_size >= size)
  189. {
  190. addrptr = addr & (FMC_FLASH_PAGE_SIZE - 1);
  191. if (addrptr)
  192. {
  193. if (nu_fmc_write(addr & ~(FMC_FLASH_PAGE_SIZE - 1), page_sdtemp, addrptr) != addrptr)
  194. goto Exit3;
  195. erased_size += addrptr;
  196. }
  197. addrptr = addr_end & (FMC_FLASH_PAGE_SIZE - 1);
  198. if (addrptr)
  199. {
  200. if (nu_fmc_write(addr_end, page_edtemp, FMC_FLASH_PAGE_SIZE - addrptr) != FMC_FLASH_PAGE_SIZE - addrptr)
  201. goto Exit3;
  202. erased_size += FMC_FLASH_PAGE_SIZE - addrptr;
  203. }
  204. }
  205. else
  206. erased_size = 0;
  207. Exit3:
  208. if (page_sdtemp != RT_NULL)
  209. rt_free(page_sdtemp);
  210. if (page_edtemp != RT_NULL)
  211. rt_free(page_edtemp);
  212. #endif
  213. return erased_size;
  214. }
  215. #if defined(PKG_USING_FAL)
  216. static int aprom_read(long offset, uint8_t *buf, size_t size)
  217. {
  218. return nu_fmc_read(Onchip_aprom_flash.addr + offset, buf, size);
  219. }
  220. static int aprom_write(long offset, const uint8_t *buf, size_t size)
  221. {
  222. return nu_fmc_write(Onchip_aprom_flash.addr + offset, buf, size);
  223. }
  224. static int aprom_erase(long offset, size_t size)
  225. {
  226. return nu_fmc_erase(Onchip_aprom_flash.addr + offset, size);
  227. }
  228. static int ldrom_read(long offset, uint8_t *buf, size_t size)
  229. {
  230. return nu_fmc_read(Onchip_ldrom_flash.addr + offset, buf, size);
  231. }
  232. static int ldrom_write(long offset, const uint8_t *buf, size_t size)
  233. {
  234. return nu_fmc_write(Onchip_ldrom_flash.addr + offset, buf, size);
  235. }
  236. static int ldrom_erase(long offset, size_t size)
  237. {
  238. return nu_fmc_erase(Onchip_ldrom_flash.addr + offset, size);
  239. }
  240. #endif /* PKG_USING_FAL */
  241. static int nu_fmc_init(void)
  242. {
  243. SYS_UnlockReg();
  244. FMC_ENABLE_ISP();
  245. SYS_LockReg();
  246. g_mutex_fmc = rt_mutex_create("nu_fmc_lock", RT_IPC_FLAG_FIFO);
  247. return (int)RT_EOK;
  248. }
  249. INIT_APP_EXPORT(nu_fmc_init);
  250. #endif /* BSP_USING_FMC */