fmc_flash.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. #include "gd32f3x0_libopt.h"
  2. #include "fmc_flash.h"
  3. #if defined (GD32F30X_HD) || defined (GD32F30X_XD) || defined (GD32F30X_CL)
  4. #define FMC_FLAG_PGERR FMC_FLAG_BANK0_PGERR
  5. #define FMC_FLAG_PGAERR FMC_FLAG_BANK0_PGERR
  6. #define FMC_FLAG_WPERR FMC_FLAG_BANK0_WPERR
  7. #define FMC_FLAG_END FMC_FLAG_BANK0_END
  8. #endif
  9. #define one_page_size 1024
  10. #define image_page_index 62
  11. #define sn_page_index 3
  12. #define data_page_index 2
  13. #define magic_page_index 1 //must is the last page in 256K eara
  14. static void _fmc_write_data(uint32_t addr, uint8_t *data, int len);
  15. static void _fmc_read_data(uint32_t addr, uint8_t *data, int len);
  16. static void _fmc_erase_addr(uint32_t addr, int len);
  17. static uint32_t _sn_addr(void);
  18. static uint32_t _data_addr(void);
  19. static uint32_t _maigc_addr(void);
  20. static uint32_t _image_addr(void);
  21. static uint32_t _image_write_addr = 0;
  22. static uint32_t _image_read_addr = 0;
  23. static u8 _image_write_cache[4];
  24. static u8 _image_write_remain;
  25. void fmc_write_sn(uint8_t *sn, int len){
  26. _fmc_erase_addr(_sn_addr(), len);
  27. _fmc_write_data(_sn_addr(), sn, len);
  28. }
  29. void fmc_read_sn(uint8_t *sn, int len){
  30. _fmc_read_data(_sn_addr(), (uint8_t *)sn, len);
  31. }
  32. void fmc_write_data(uint8_t *data, int len){
  33. _fmc_erase_addr(_data_addr(), len);
  34. _fmc_write_data(_data_addr(), data, len);
  35. }
  36. void fmc_read_data(uint8_t *data, int len){
  37. _fmc_read_data(_data_addr(), data, len);
  38. }
  39. void fmc_erase_image(void){
  40. _fmc_erase_addr(_image_addr(), one_page_size * 50);
  41. _image_write_addr = 0;
  42. }
  43. void fmc_write_image(uint8_t *data, int len){
  44. _fmc_write_data(_image_addr() + _image_write_addr, data, len);
  45. _image_write_addr += len;
  46. }
  47. void fmc_write_image_begin(void)
  48. {
  49. _image_write_addr = _image_addr();
  50. _image_write_remain = 0;
  51. }
  52. static void fmc_write_image_flush(void)
  53. {
  54. u32 value = *(u32 *) _image_write_cache;
  55. if ((_image_write_addr % one_page_size) == 0) {
  56. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  57. fmc_page_erase(_image_write_addr);
  58. }
  59. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  60. fmc_word_program(_image_write_addr, value);
  61. _image_write_remain = 0;
  62. _image_write_addr += 4;
  63. }
  64. void fmc_write_image_continue(const u8 *data, int len)
  65. {
  66. const u8 *data_end;
  67. fmc_unlock();
  68. for (data_end = data + len; data < data_end; data++) {
  69. if (_image_write_remain >= sizeof(_image_write_cache)) {
  70. fmc_write_image_flush();
  71. }
  72. _image_write_cache[_image_write_remain] = *data;
  73. _image_write_remain++;
  74. }
  75. fmc_lock();
  76. }
  77. void fmc_write_image_end(void)
  78. {
  79. if (_image_write_remain > 0) {
  80. fmc_unlock();
  81. fmc_write_image_flush();
  82. fmc_lock();
  83. }
  84. }
  85. void fmc_start_read_image(void){
  86. _image_read_addr = 0;
  87. }
  88. void fmc_read_image(uint8_t *data, int len){
  89. _fmc_read_data(_image_addr() + _image_read_addr, data, len);
  90. _image_read_addr += len;
  91. }
  92. uint32_t fmc_iap_image_addr(void){
  93. return _image_addr();
  94. }
  95. void fmc_iap_write_magic(uint32_t magic)
  96. {
  97. uint32_t address = _maigc_addr();
  98. uint32_t length, checksum, value;
  99. value = REG32(address + 8);
  100. if (magic == value) {
  101. return;
  102. }
  103. length = REG32(address);
  104. checksum = REG32(address + 4);
  105. fmc_unlock();
  106. if (value != 0xFFFFFFFF) {
  107. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  108. fmc_page_erase(address);
  109. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  110. fmc_word_program(address, length);
  111. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  112. fmc_word_program(address + 4, checksum);
  113. }
  114. if (magic != 0xFFFFFFFF) {
  115. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  116. fmc_word_program(address + 8, magic);
  117. }
  118. fmc_lock();
  119. }
  120. void fmc_write_magic(uint32_t length, uint32_t checksum, uint32_t magic){
  121. uint32_t address = _maigc_addr();
  122. uint32_t buff[4];
  123. buff[0] = length;
  124. buff[1] = checksum;
  125. buff[2] = magic;
  126. buff[3] = _image_addr();
  127. _fmc_erase_addr(_maigc_addr(), sizeof(buff));
  128. _fmc_write_data(_maigc_addr(), (uint8_t *)buff ,sizeof(buff));
  129. }
  130. uint32_t fmc_read_magic(void){
  131. uint32_t magic = 0x5555aaaa;
  132. _fmc_read_data(_maigc_addr(), (uint8_t *)&magic, sizeof(magic));
  133. return magic;
  134. }
  135. //if flash is lager than 256k, we just use the 256k
  136. static uint32_t __inline__ _flash_capatity(void){
  137. uint32_t capacity;
  138. capacity = (REG32(0x1FFFF7E0) & 0xFFFF) << 10;
  139. if (capacity > (256 * 1024)){
  140. capacity = 256 * 1024;
  141. }
  142. return capacity;
  143. }
  144. uint32_t gd32_flash_size(void){
  145. return _flash_capatity();
  146. }
  147. static uint32_t _sn_addr(void){
  148. return 0x08000000 + (_flash_capatity() - one_page_size * sn_page_index);
  149. }
  150. static uint32_t _data_addr(void){
  151. return 0x08000000 + (_flash_capatity() - one_page_size * data_page_index);
  152. }
  153. static uint32_t _maigc_addr(void){
  154. return 0x08000000 + (_flash_capatity() - one_page_size * magic_page_index);
  155. }
  156. static uint32_t _image_addr(void){
  157. return 0x08000000 + (one_page_size * image_page_index);
  158. }
  159. static void _fmc_read_data(uint32_t addr, uint8_t *data, int len){
  160. int i = 0;
  161. for (i = 0; i < len; i++){
  162. data[i] = REG8(addr + i);
  163. }
  164. }
  165. extern void wdog_reload(void);
  166. static void _fmc_erase_addr(uint32_t addr, int len){
  167. fmc_unlock();
  168. uint32_t pages = len/one_page_size + (((len % one_page_size) > 0)?1:0);
  169. for (int i = 0; i < pages; i++){
  170. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  171. fmc_page_erase(addr + i * one_page_size);
  172. wdog_reload();
  173. }
  174. fmc_lock();
  175. }
  176. static void _fmc_write_data(uint32_t addr, uint8_t *data, int len){
  177. fmc_unlock();
  178. int total_words = len / 4;
  179. uint32_t *p_u32_data = (uint32_t *)data;
  180. int i;
  181. for (i = 0; i < total_words; i++){
  182. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  183. fmc_word_program(addr, p_u32_data[i]);
  184. data += 4;
  185. addr += 4;
  186. }
  187. int remain_len = len - total_words * 4;
  188. if (remain_len > 0){
  189. uint32_t words = 0;
  190. for (int i = 0; i < remain_len; i++){
  191. words |= data[i] << (8*i);
  192. }
  193. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  194. fmc_word_program(addr, words);
  195. }
  196. fmc_lock();
  197. }