drv_fmc.c 8.2 KB

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