drv_fmc.c 8.4 KB

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