fmc_flash.c 4.9 KB

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