fmc_flash.c 4.9 KB

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