fmc_flash.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include "bsp/bsp_driver.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. static void _fmc_write_data(uint32_t addr, uint8_t *data, int len);
  9. static void _fmc_read_data(uint32_t addr, uint8_t *data, int len);
  10. static void _fmc_erase_addr(uint32_t addr, int len);
  11. static void _fmc_read_data(uint32_t addr, uint8_t *data, int len);
  12. static void _fmc_erase_write_data(uint32_t addr, uint8_t *data, int len);
  13. static uint32_t _sn_addr(void);
  14. static uint32_t _data_addr(int index);
  15. static uint32_t _maigc_addr(void);
  16. static uint32_t _nv_tbl_write_addr = 0;
  17. static u8 _nv_tbl_write_cache[4];
  18. static u8 _nv_tbl_write_remain;
  19. void fmc_write_sn(uint8_t *sn, int len){
  20. _fmc_erase_write_data(_sn_addr(), sn, len);
  21. }
  22. void fmc_read_sn(uint8_t *sn, int len){
  23. _fmc_read_data(_sn_addr(), sn, len);
  24. }
  25. void fmc_write_data(int index, uint8_t *data, int len){
  26. _fmc_erase_write_data(_data_addr(index), data, len);
  27. }
  28. void fmc_read_data(int index, uint8_t *data, int len){
  29. _fmc_read_data(_data_addr(index), data, len);
  30. }
  31. void fmc_read_data_with_offset(int index, u32 off, uint8_t *data, int len) {
  32. uint32_t addr = _data_addr(index) + off;
  33. _fmc_read_data(addr, data, len);
  34. }
  35. static __inline__ void _fmc_flag_clear(void) {
  36. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  37. }
  38. void fmc_write_magic(uint32_t magic){
  39. uint32_t address = _maigc_addr();
  40. uint32_t length, checksum, value;
  41. value = REG32(address + 8);
  42. if (magic == value) {
  43. return;
  44. }
  45. length = REG32(address);
  46. checksum = REG32(address + 4);
  47. fmc_unlock();
  48. if (value != 0xFFFFFFFF) {
  49. _fmc_flag_clear();
  50. fmc_page_erase(address);
  51. _fmc_flag_clear();
  52. fmc_word_program(address, length);
  53. _fmc_flag_clear();
  54. fmc_word_program(address + 4, checksum);
  55. }
  56. if (magic != 0xFFFFFFFF) {
  57. _fmc_flag_clear();
  58. fmc_word_program(address + 8, magic);
  59. }
  60. fmc_lock();
  61. }
  62. uint32_t fmc_read_magic(void){
  63. uint32_t magic = 0x5555aaaa;
  64. _fmc_read_data(_maigc_addr(), (uint8_t *)&magic, sizeof(magic));
  65. return magic;
  66. }
  67. //if flash is lager than 256k, we just use the 256k
  68. static uint32_t __inline__ _flash_capatity(void){
  69. uint32_t capacity;
  70. capacity = (REG32(0x1FFFF7E0) & 0xFFFF) << 10;
  71. if (capacity > (256 * 1024)){
  72. capacity = 256 * 1024;
  73. }
  74. return capacity;
  75. }
  76. static uint32_t _sn_addr(void){
  77. return 0x08000000 + (_flash_capatity() - one_page_size * sn_page_index);
  78. }
  79. static uint32_t _data_addr(int index){
  80. return 0x08000000 + (_flash_capatity() - one_page_size * index);
  81. }
  82. static uint32_t _maigc_addr(void){
  83. return 0x08000000 + (_flash_capatity() - one_page_size * magic_page_index);
  84. }
  85. static void _fmc_read_data(uint32_t addr, uint8_t *data, int len){
  86. int i = 0;
  87. for (i = 0; i < len; i++){
  88. data[i] = REG8(addr + i);
  89. }
  90. }
  91. uint32_t fmc_get_addr(int page) {
  92. return 0x08000000 + (_flash_capatity() - one_page_size * page);
  93. }
  94. void fmc_erase_trq_table(int addr, int len){
  95. _fmc_erase_addr(addr, len);
  96. _nv_tbl_write_addr = 0;
  97. }
  98. void fmc_write_trq_table(int addr, uint8_t *data, int len){
  99. _fmc_write_data(addr + _nv_tbl_write_addr, data, len);
  100. _nv_tbl_write_addr += len;
  101. }
  102. void fmc_write_trq_table_begin(int addr)
  103. {
  104. _nv_tbl_write_addr = addr;
  105. _nv_tbl_write_remain = 0;
  106. }
  107. static void fmc_write_trq_table_flush(void)
  108. {
  109. u32 value = *(u32 *) _nv_tbl_write_cache;
  110. if ((_nv_tbl_write_addr % one_page_size) == 0) {
  111. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  112. fmc_page_erase(_nv_tbl_write_addr);
  113. }
  114. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  115. fmc_word_program(_nv_tbl_write_addr, value);
  116. _nv_tbl_write_addr += _nv_tbl_write_remain;
  117. _nv_tbl_write_remain = 0;
  118. }
  119. void fmc_write_trq_table_continue(const u8 *data, int len)
  120. {
  121. const u8 *data_end;
  122. fmc_unlock();
  123. for (data_end = data + len; data < data_end; data++) {
  124. if (_nv_tbl_write_remain >= sizeof(_nv_tbl_write_cache)) {
  125. fmc_write_trq_table_flush();
  126. }
  127. _nv_tbl_write_cache[_nv_tbl_write_remain] = *data;
  128. _nv_tbl_write_remain++;
  129. }
  130. fmc_lock();
  131. }
  132. void fmc_write_trq_table_end(void)
  133. {
  134. if (_nv_tbl_write_remain > 0) {
  135. fmc_unlock();
  136. fmc_write_trq_table_flush();
  137. fmc_lock();
  138. }
  139. }
  140. extern void wdog_reload(void);
  141. static void _fmc_erase_addr(uint32_t addr, int len){
  142. fmc_unlock();
  143. uint32_t pages = len/one_page_size + (((len % one_page_size) > 0)?1:0);
  144. for (int i = 0; i < pages; i++){
  145. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  146. fmc_page_erase(addr + i * one_page_size);
  147. wdog_reload();
  148. }
  149. fmc_lock();
  150. }
  151. static void _fmc_write_data(uint32_t addr, uint8_t *data, int len){
  152. fmc_unlock();
  153. int total_words = len / 4;
  154. uint32_t *p_u32_data = (uint32_t *)data;
  155. int i;
  156. for (i = 0; i < total_words; i++){
  157. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  158. fmc_word_program(addr, p_u32_data[i]);
  159. data += 4;
  160. addr += 4;
  161. }
  162. int remain_len = len - total_words * 4;
  163. if (remain_len > 0){
  164. uint32_t words = 0;
  165. for (int i = 0; i < remain_len; i++){
  166. words |= data[i] << (8*i);
  167. }
  168. fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_WPERR | FMC_FLAG_END);
  169. fmc_word_program(addr, words);
  170. }
  171. fmc_lock();
  172. }
  173. static void _fmc_erase_write_data(uint32_t addr, uint8_t *data, int len){
  174. _fmc_erase_addr(addr, len);
  175. _fmc_write_data(addr, data, len);
  176. }