SN_FLASH.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include "SN_FLASH.h"
  2. /*
  3. 文件名:SN_FLASH.c/.h
  4. 作者: SN_FAE_黄泽洪
  5. 免责声明:无版权,可随意传播和篡改,该代码仅供开发参考,如需使用请自行验证
  6. 本人不担负商业使用上带来的风险。
  7. */
  8. /*
  9. SN_FLASH 模块使用方法是:
  10. 注意: flash有十万次擦写寿命,SN_FLASH_Write_PAGE 千万不要放在死循环里面。
  11. //写入flash数据
  12. uint8_t flash_data_in[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  13. //读出flash数据
  14. uint8_t flash_data_out[20] = {0};
  15. int main(void)
  16. {
  17. SN_SYSCLK_set(SYSCLK_48MHZ);
  18. std_delay_init();
  19. //写入flash数据,扇区选择后面的,不能使用写有代码的扇区
  20. SN_FLASH_Write_PAGE(0x20,flash_data_in, 12);
  21. SN_FLASH_ReadE(0x00004000, flash_data_out, 12);
  22. while(1);
  23. }
  24. */
  25. /*
  26. 函数:SN_FLASH_Write_PAGE(uint8_t PAGE_NUM,uint8_t * data , uint16_t len)
  27. 功能:往一个扇区里面写入最大支持512个字节长度的数据
  28. 每次写入同一个扇区,该扇区的512个字节都会被擦除
  29. 然后重新写入数据,如果要往同一个扇区写入新数据,
  30. 并且保留部分旧数据。就要把这部分旧数据先读取出来,
  31. 然后在合在一起,重新写入该扇区。
  32. 由于003只有3k的sram,所为该接口不考虑开辟缓冲空间
  33. 写入操作都是按扇区的,如果需要跨扇区操作,需要用户
  34. 自行完成
  35. 参数:扇区号 (注意不要写在代码处) 范围:( 0 - 47 )
  36. 参数:数组
  37. 参数:数组长度(现在长度512字节)
  38. 返回:成功0 失败1
  39. */
  40. uint8_t SN_FLASH_Write_PAGE(uint8_t PAGE_NUM, uint8_t *data1, uint16_t len)
  41. {
  42. uint16_t LEN = len / 4;
  43. uint8_t *data = data1;
  44. uint16_t remainder = (len % 4); // 不对齐4位的字节数是多少
  45. uint32_t temp = 0, temp1 = 0, word_count = 0; // 中间变量
  46. std_flash_clear_flag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR); // 清除所有标志位
  47. std_flash_unlock(); // 关闭flash控制寄存器锁
  48. if (STD_OK != std_flash_erase(FLASH_MODE_PAGE_ERASE, (PAGE_NUM * 0x200)))
  49. return 1; // flash擦除
  50. // 对齐处理
  51. if (LEN)
  52. {
  53. for (word_count = 0; word_count < LEN; word_count++)
  54. {
  55. for (int i = 0; i < 4; i++)
  56. { // 4字节合并成一个字
  57. temp1 = ((uint32_t)data[word_count * 4 + i]) << (i * 8);
  58. temp |= temp1;
  59. }
  60. // 写入32bit
  61. if (STD_OK != std_flash_word_program(((PAGE_NUM * 0x200) + ((word_count) * 4)), temp))
  62. return 1;
  63. temp = 0;
  64. temp1 = 0;
  65. }
  66. if (!remainder)
  67. return 0; // 刚好对齐没有尾部
  68. }
  69. // 不对齐处理
  70. switch (remainder)
  71. {
  72. case 1:
  73. temp |= ((uint32_t)data[len - 1]) | 0xffffff00;
  74. break;
  75. case 2:
  76. temp1 = ((uint32_t)data[len - 1]) << 8;
  77. temp1 |= ((uint32_t)data[len - 2]);
  78. temp = temp1 | 0xffff0000;
  79. break;
  80. case 3:
  81. temp1 = ((uint32_t)data[len - 1]) << 16;
  82. temp1 |= ((uint32_t)data[len - 2]) << 8;
  83. temp1 |= ((uint32_t)data[len - 3]);
  84. temp = temp1 | 0xff000000;
  85. break;
  86. default:
  87. return 0;
  88. }
  89. if (LEN)
  90. {
  91. if (STD_OK != std_flash_word_program((PAGE_NUM * 0x200) + (LEN * 4), temp))
  92. return 1; // 尾部不对齐
  93. }
  94. else
  95. {
  96. if (STD_OK != std_flash_word_program((PAGE_NUM * 0x200), temp))
  97. return 1; // 头部不凑整
  98. }
  99. // 开启flash控制寄存器锁
  100. std_flash_lock();
  101. return 0;
  102. }
  103. /*
  104. 函数:SN_FLASH_ReadE(uint8_t flash_add, uint8_t* date, uint16_t len)
  105. 功能:检查扇区是否为空
  106. 参数:物理地址 (扇区转换为物理地址: flash_add = 扇区号*512)
  107. 参数:接收数组
  108. 参数:数组长度
  109. 返回:无
  110. */
  111. void SN_FLASH_ReadE(uint32_t flash_add, uint8_t *date, uint16_t len)
  112. {
  113. uint16_t word_count;
  114. for (word_count = 0; word_count < len; word_count++)
  115. {
  116. date[word_count] = *(uint8_t *)(flash_add + word_count);
  117. }
  118. }
  119. /*
  120. 函数:SN_FLASH_PAGE_null(uint8_t PAGE_NUM)
  121. 功能:检查扇区是否为空
  122. 参数:扇区号
  123. 返回:空返回 0 非空返回 1
  124. */
  125. uint8_t SN_FLASH_PAGE_null(uint8_t PAGE_NUM)
  126. {
  127. uint16_t word_count = 0;
  128. uint16_t count = 512 >> 4;
  129. for (word_count = 0; word_count < count; word_count++)
  130. {
  131. /* 校验编程数据 */
  132. if (*(uint32_t *)(0x00000000 + (word_count << 2)) != 0xffffffff)
  133. {
  134. return 1;
  135. }
  136. }
  137. return 0;
  138. }
  139. /*
  140. 函数:SN_MUC_UID(uint32_t UID[3])
  141. 功能:检查扇区是否为空
  142. 参数:接收96位UID的数组
  143. 返回:无
  144. */
  145. void SN_MUC_UID(uint32_t UID[3])
  146. {
  147. UID[0] = *((uint32_t *)0x1FFF0340 + 0);
  148. UID[1] = *((uint32_t *)0x1FFF0340 + 1);
  149. UID[2] = *((uint32_t *)0x1FFF0340 + 2);
  150. }