drv_fmc.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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. * 2022-3-16 Wayne 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(RT_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(RT_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 /* RT_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(RT_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 /* RT_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. uint32_t u32RegLockBackup = SYS_IsRegLocked();
  52. SYS_UnlockReg();
  53. if (NU_GET_LSB2BIT(addr))
  54. isp_rdata = FMC_Read(NU_GET_WALIGN(addr));
  55. for (; addr < addr_end ;)
  56. {
  57. if (NU_GET_LSB2BIT(addr) == 0)
  58. {
  59. isp_rdata = FMC_Read(addr);
  60. if (addr_end - addr >= 4)
  61. {
  62. *(uint32_t *)buf = isp_rdata;
  63. addr += 4;
  64. buf += 4;
  65. read_size += 4;
  66. continue;
  67. }
  68. }
  69. *buf = isp_rdata >> NU_GETBYTE_OFST(addr);
  70. addr++;
  71. buf++;
  72. read_size++;
  73. }
  74. if (u32RegLockBackup)
  75. SYS_LockReg();
  76. rt_mutex_release(g_mutex_fmc);
  77. return read_size;
  78. }
  79. int nu_fmc_write(long addr, const uint8_t *buf, size_t size)
  80. {
  81. size_t write_size = 0;
  82. uint32_t addr_end = addr + size;
  83. uint32_t isp_rdata = 0;
  84. rt_mutex_take(g_mutex_fmc, RT_WAITING_FOREVER);
  85. uint32_t u32RegLockBackup = SYS_IsRegLocked();
  86. SYS_UnlockReg();
  87. if (addr < FMC_APROM_END)
  88. FMC_ENABLE_AP_UPDATE();
  89. else if ((addr < FMC_LDROM_END) && addr >= FMC_LDROM_BASE)
  90. FMC_ENABLE_LD_UPDATE();
  91. else
  92. {
  93. goto Exit2;
  94. }
  95. if (NU_GET_LSB2BIT(addr))
  96. isp_rdata = FMC_Read(NU_GET_WALIGN(addr));
  97. for (; addr < addr_end ;)
  98. {
  99. if (addr_end - addr >= 4 && NU_GET_LSB2BIT(addr) == 0)
  100. {
  101. FMC_Write(addr, *((uint32_t *)buf));
  102. addr += 4;
  103. buf += 4;
  104. write_size += 4;
  105. continue;
  106. }
  107. if ((NU_GET_LSB2BIT(addr)) == 0x0)
  108. isp_rdata = FMC_Read(NU_GET_WALIGN(addr));
  109. isp_rdata = (isp_rdata & ~(0xFF << NU_GETBYTE_OFST(addr))) | ((*buf) << NU_GETBYTE_OFST(addr));
  110. if ((NU_GET_LSB2BIT(addr)) == 0x3)
  111. FMC_Write(NU_GET_WALIGN(addr), isp_rdata);
  112. addr++;
  113. buf++;
  114. write_size++;
  115. }
  116. if (NU_GET_LSB2BIT(addr))
  117. FMC_Write(NU_GET_WALIGN(addr), isp_rdata);
  118. FMC_DISABLE_AP_UPDATE();
  119. FMC_DISABLE_LD_UPDATE();
  120. Exit2:
  121. if (u32RegLockBackup)
  122. SYS_LockReg();
  123. rt_mutex_release(g_mutex_fmc);
  124. return write_size;
  125. }
  126. int nu_fmc_erase(long addr, size_t size)
  127. {
  128. size_t erased_size = 0;
  129. uint32_t addrptr;
  130. uint32_t addr_end = addr + size;
  131. uint32_t u32RegLockBackup;
  132. #if defined(NU_SUPPORT_NONALIGN)
  133. uint8_t *page_sdtemp = RT_NULL;
  134. uint8_t *page_edtemp = RT_NULL;
  135. addrptr = addr & (FMC_FLASH_PAGE_SIZE - 1);
  136. if (addrptr)
  137. {
  138. page_sdtemp = rt_malloc(addrptr);
  139. if (page_sdtemp == RT_NULL)
  140. {
  141. erased_size = 0;
  142. goto Exit3;
  143. }
  144. if (nu_fmc_read(addr & ~(FMC_FLASH_PAGE_SIZE - 1), page_sdtemp, addrptr) != addrptr)
  145. {
  146. erased_size = 0;
  147. goto Exit3;
  148. }
  149. }
  150. addrptr = addr_end & (FMC_FLASH_PAGE_SIZE - 1);
  151. if (addrptr)
  152. {
  153. page_edtemp = rt_malloc(FMC_FLASH_PAGE_SIZE - addrptr);
  154. if (page_edtemp == RT_NULL)
  155. {
  156. erased_size = 0;
  157. goto Exit3;
  158. }
  159. if (nu_fmc_read(addr_end, page_edtemp, FMC_FLASH_PAGE_SIZE - addrptr) != FMC_FLASH_PAGE_SIZE - addrptr)
  160. {
  161. erased_size = 0;
  162. goto Exit3;
  163. }
  164. }
  165. #endif
  166. rt_mutex_take(g_mutex_fmc, RT_WAITING_FOREVER);
  167. u32RegLockBackup = SYS_IsRegLocked();
  168. SYS_UnlockReg();
  169. if (addr <= FMC_APROM_END)
  170. FMC_ENABLE_AP_UPDATE();
  171. else if ((addr < FMC_LDROM_END) && addr >= FMC_LDROM_BASE)
  172. FMC_ENABLE_LD_UPDATE();
  173. else
  174. {
  175. goto Exit2;
  176. }
  177. addrptr = (addr & ~(FMC_FLASH_PAGE_SIZE - 1));
  178. while (addrptr < addr_end)
  179. {
  180. if (FMC_Erase(addrptr) != RT_EOK)
  181. {
  182. goto Exit1;
  183. }
  184. erased_size += FMC_FLASH_PAGE_SIZE;
  185. addrptr += FMC_FLASH_PAGE_SIZE;
  186. }
  187. Exit1:
  188. FMC_DISABLE_AP_UPDATE();
  189. FMC_DISABLE_LD_UPDATE();
  190. Exit2:
  191. if (u32RegLockBackup)
  192. SYS_LockReg();
  193. rt_mutex_release(g_mutex_fmc);
  194. #if defined(NU_SUPPORT_NONALIGN)
  195. if (erased_size >= size)
  196. {
  197. addrptr = addr & (FMC_FLASH_PAGE_SIZE - 1);
  198. if (addrptr)
  199. {
  200. if (nu_fmc_write(addr & ~(FMC_FLASH_PAGE_SIZE - 1), page_sdtemp, addrptr) != addrptr)
  201. goto Exit3;
  202. erased_size += addrptr;
  203. }
  204. addrptr = addr_end & (FMC_FLASH_PAGE_SIZE - 1);
  205. if (addrptr)
  206. {
  207. if (nu_fmc_write(addr_end, page_edtemp, FMC_FLASH_PAGE_SIZE - addrptr) != FMC_FLASH_PAGE_SIZE - addrptr)
  208. goto Exit3;
  209. erased_size += FMC_FLASH_PAGE_SIZE - addrptr;
  210. }
  211. }
  212. else
  213. erased_size = 0;
  214. Exit3:
  215. if (page_sdtemp != RT_NULL)
  216. rt_free(page_sdtemp);
  217. if (page_edtemp != RT_NULL)
  218. rt_free(page_edtemp);
  219. #endif
  220. return erased_size;
  221. }
  222. #if defined(RT_USING_FAL)
  223. static int aprom_read(long offset, uint8_t *buf, size_t size)
  224. {
  225. return nu_fmc_read(Onchip_aprom_flash.addr + offset, buf, size);
  226. }
  227. static int aprom_write(long offset, const uint8_t *buf, size_t size)
  228. {
  229. return nu_fmc_write(Onchip_aprom_flash.addr + offset, buf, size);
  230. }
  231. static int aprom_erase(long offset, size_t size)
  232. {
  233. return nu_fmc_erase(Onchip_aprom_flash.addr + offset, size);
  234. }
  235. static int ldrom_read(long offset, uint8_t *buf, size_t size)
  236. {
  237. return nu_fmc_read(Onchip_ldrom_flash.addr + offset, buf, size);
  238. }
  239. static int ldrom_write(long offset, const uint8_t *buf, size_t size)
  240. {
  241. return nu_fmc_write(Onchip_ldrom_flash.addr + offset, buf, size);
  242. }
  243. static int ldrom_erase(long offset, size_t size)
  244. {
  245. return nu_fmc_erase(Onchip_ldrom_flash.addr + offset, size);
  246. }
  247. #endif /* RT_USING_FAL */
  248. static int nu_fmc_init(void)
  249. {
  250. uint32_t u32RegLockBackup = SYS_IsRegLocked();
  251. SYS_UnlockReg();
  252. FMC_ENABLE_ISP();
  253. if (u32RegLockBackup)
  254. SYS_LockReg();
  255. g_mutex_fmc = rt_mutex_create("nu_fmc_lock", RT_IPC_FLAG_PRIO);
  256. RT_ASSERT(g_mutex_fmc);
  257. /* RT_USING_FAL */
  258. #if defined(RT_USING_FAL)
  259. fal_init();
  260. #endif
  261. return (int)RT_EOK;
  262. }
  263. INIT_APP_EXPORT(nu_fmc_init);
  264. #endif /* BSP_USING_FMC */