fmc.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #include "gd32f10x.h"
  2. #include "fmc.h"
  3. /*--------------------------------------------------*/
  4. /*函数名:按页擦除FLASH */
  5. /*参 数:start:擦除起始页 num:擦几个页 */
  6. /*返回值:无 */
  7. /*
  8. flash结构:
  9. 0x08000000~0x0807FFFF bank0(2KB一页,0~255页,共256页)共512KB
  10. 0x08080000~0x082FFFFF bank1(4KB一页,256~895页,共640页)共2.5MB 这个分区连续读内存需要有延时
  11. */
  12. /*-------------------------------------------------*/
  13. void GD32_EraseFlash(uint16_t start, uint16_t num)
  14. {
  15. uint16_t i; //用于for循环
  16. uint16_t j = 0;
  17. if ((start <= 896) && (start + num) > 896)
  18. {
  19. num = 896 - start;
  20. }
  21. else if (start > 896)
  22. {
  23. return;
  24. }
  25. fmc_unlock(); //解锁
  26. if ((start < 256) && ((start + num) < 256))
  27. {
  28. for(i = 0; i < num; i++) //循环num次,一个页一个页的擦除
  29. {
  30. fmc_page_erase((0x08000000 + start * 2048) + (2048 * i)); //擦除bank0一个页2KB
  31. }
  32. }
  33. else if ((start < 256) && ((start + num) > 256))
  34. {
  35. for(i = 0; i < num; i++) //循环num次,一个页一个页的擦除
  36. {
  37. if((start + i) < 256)
  38. {
  39. fmc_page_erase((0x08000000 + start * 2 * 1024) + (2 * 1024 * i)); //擦除bank0一个页2KB
  40. }
  41. else
  42. {
  43. fmc_page_erase(0x08080000 + (4 * 1024 * j)); //擦除bank1一个页4KB
  44. j++;
  45. }
  46. }
  47. }
  48. else if (start > 256)
  49. {
  50. for(i = 0; i < num; i++) //循环num次,一个页一个页的擦除
  51. {
  52. fmc_page_erase((0x08080000 + (start - 256) * 4 * 1024) + (4 * 1024 * i)); //擦除bank1一个页4KB
  53. }
  54. }
  55. fmc_lock(); //上锁
  56. }
  57. /*---------------------------------------------------------------------*/
  58. /*函数名:写入FLASH */
  59. /*参 数:saddr:写入地址 wdata:写入数据指针 wnum:写入多少个字节 */
  60. /*返回值:无 */
  61. /*---------------------------------------------------------------------*/
  62. void GD32_WriteFlash(uint32_t saddr, uint32_t *wdata, uint32_t wnum)
  63. {
  64. fmc_unlock(); //解锁
  65. while(wnum){ //循环写入,知道num等于0退出while,表示写入完毕
  66. fmc_word_program(saddr,*wdata); //写入一个字(4个字节)
  67. wnum-=4; //写入字节数量-4
  68. saddr+=4; //写入地址+4
  69. wdata++; //写入数据的指针,往后挪动一次
  70. }
  71. fmc_lock(); //上锁
  72. }
  73. // /**
  74. // * @brief 读取flash数据
  75. // *
  76. // * @param rbuff 接收缓冲区
  77. // * @param addr 起始地址,32位地址
  78. // * @param datalen 数据长度,多少个字节
  79. // */
  80. // void GD32_ReadFlash(uint8_t *rbuff, uint32_t addr, uint32_t datalen)
  81. // {
  82. // memcpy(rbuff,addr,datalen);
  83. // }
  84. __align(4) static uint16_t FlashBuffer[GD32FLASH_PAGE_SIZE >> 1];
  85. /// 初始化FLASH
  86. void FLASH_Init(void)
  87. {
  88. fmc_unlock();
  89. fmc_flag_clear(FMC_FLAG_BANK0_END);
  90. fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
  91. fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
  92. fmc_lock();
  93. }
  94. /**
  95. * 读FLASH
  96. * @param Address 地址
  97. * @param Buffer 存放读取的数据
  98. * @param Size 要读取的数据大小,单位字节
  99. * @return 读出成功的字节数
  100. */
  101. uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size)
  102. {
  103. uint32_t nread = Size;
  104. uint8_t* d = (uint8_t *)Buffer;
  105. const uint8_t* s = (const uint8_t *)Address;
  106. if (!Buffer || Address < GD32FLASH_BASE || Address >= GD32FLASH_END)
  107. return 0;
  108. while (nread >= sizeof(uint32_t) && (((uint32_t)s) <= (GD32FLASH_END - 4)))
  109. {
  110. *(volatile uint32_t *)d = *(volatile uint32_t *)s;
  111. d += sizeof(uint32_t);
  112. s += sizeof(uint32_t);
  113. nread -= sizeof(uint32_t);
  114. }
  115. while (nread && (((uint32_t)s) < GD32FLASH_END))
  116. {
  117. *d++ = *s++;
  118. nread--;
  119. }
  120. return Size - nread;
  121. }
  122. /**
  123. * 写FLASH
  124. * @param Address 写入起始地址,!!!要求2字节对齐!!!
  125. * @param Buffer 待写入的数据,!!!要求2字节对齐!!!
  126. * @param NumToWrite 要写入的数据量,单位:半字,!!!要求2字节对齐!!!
  127. * @return 实际写入的数据量,单位:字节
  128. */
  129. uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
  130. {
  131. uint32_t i = 0;
  132. uint32_t pagepos = 0; // 页位置
  133. uint32_t pageoff = 0; // 页内偏移地址
  134. uint32_t pagefre = 0; // 页内空余空间
  135. uint32_t offset = 0; // Address在FLASH中的偏移
  136. uint32_t nwrite = NumToWrite; // 记录剩余要写入的数据量
  137. const uint16_t *pBuffer = (const uint16_t *)Buffer;
  138. /* 非法地址 */
  139. if (Address < GD32FLASH_BASE || Address > (GD32FLASH_END - 2) || NumToWrite == 0 || pBuffer == NULL)
  140. return 0;
  141. /* 解锁FLASH */
  142. fmc_unlock();
  143. /* 计算偏移地址 */
  144. offset = Address - GD32FLASH_BASE;
  145. /* 计算当前页位置 */
  146. pagepos = offset / GD32FLASH_PAGE_SIZE;
  147. /* 计算要写数据的起始地址在当前页内的偏移地址 */
  148. pageoff = ((offset % GD32FLASH_PAGE_SIZE) >> 1);
  149. /* 计算当前页内空余空间 */
  150. pagefre = ((GD32FLASH_PAGE_SIZE >> 1) - pageoff);
  151. /* 要写入的数据量低于当前页空余量 */
  152. if (nwrite <= pagefre)
  153. pagefre = nwrite;
  154. while (nwrite != 0)
  155. {
  156. /* 检查是否超页 */
  157. if (pagepos >= GD32FLASH_PAGE_NUM)
  158. break;
  159. /* 读取一页 */
  160. FLASH_Read(GD32FLASH_BASE + pagepos * GD32FLASH_PAGE_SIZE, FlashBuffer, GD32FLASH_PAGE_SIZE);
  161. /* 检查是否需要擦除 */
  162. for (i = 0; i < pagefre; i++)
  163. {
  164. if (*(FlashBuffer + pageoff + i) != 0xFFFF) /* FLASH擦出后默认内容全为0xFF */
  165. break;
  166. }
  167. if (i < pagefre)
  168. {
  169. uint32_t count = 0;
  170. uint32_t index = 0;
  171. if(FLASH_ErasePage(GD32FLASH_BASE + pagepos * GD32FLASH_PAGE_SIZE, 1) < 0)
  172. break;
  173. /* 复制到缓存 */
  174. for (index = 0; index < pagefre; index++)
  175. {
  176. *(FlashBuffer + pageoff + index) = *(pBuffer + index);
  177. }
  178. /* 写回FLASH */
  179. count = FLASH_WriteNotErase(GD32FLASH_BASE + pagepos * GD32FLASH_PAGE_SIZE, FlashBuffer, GD32FLASH_PAGE_SIZE >> 1);
  180. if (count != (GD32FLASH_PAGE_SIZE >> 1))
  181. {
  182. nwrite -= count;
  183. break;
  184. }
  185. }
  186. else
  187. {
  188. /* 无需擦除,直接写 */
  189. uint32_t count = FLASH_WriteNotErase(Address, pBuffer, pagefre);
  190. if (count != pagefre)
  191. {
  192. nwrite -= count;
  193. break;
  194. }
  195. }
  196. pBuffer += pagefre; /* 读取地址递增 */
  197. Address += (pagefre << 1); /* 写入地址递增 */
  198. nwrite -= pagefre; /* 更新剩余未写入数据量 */
  199. pagepos++; /* 下一页 */
  200. pageoff = 0; /* 页内偏移地址置零 */
  201. /* 根据剩余量计算下次写入数据量 */
  202. pagefre = nwrite >= (GD32FLASH_PAGE_SIZE >> 1) ? (GD32FLASH_PAGE_SIZE >> 1) : nwrite;
  203. }
  204. /* 加锁FLASH */
  205. fmc_lock();
  206. return ((NumToWrite - nwrite) << 1);
  207. }
  208. uint32_t FLASH_WriteNotErase(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
  209. {
  210. uint32_t nwrite = NumToWrite;
  211. uint32_t addrmax = GD32FLASH_END - 2;
  212. while (nwrite)
  213. {
  214. if (Address > addrmax)
  215. break;
  216. fmc_halfword_program(Address, *Buffer);
  217. if ((*(__IO uint16_t*) Address) != *Buffer)
  218. break;
  219. nwrite--;
  220. Buffer++;
  221. Address += 2;
  222. }
  223. return (NumToWrite - nwrite);
  224. }
  225. int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages)
  226. {
  227. while(NbPages--)
  228. {
  229. if(fmc_page_erase(PageAddress) != FMC_READY)
  230. {
  231. return -1;
  232. }
  233. PageAddress += GD32FLASH_PAGE_SIZE;
  234. }
  235. return 0;
  236. }