SN_FLASH.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. uint16_t LEN = len / 4 ;
  42. uint8_t *data = data1;
  43. uint16_t remainder = (len % 4); //不对齐4位的字节数是多少
  44. uint32_t temp = 0 , temp1 = 0 ,word_count = 0; //中间变量
  45. std_flash_clear_flag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR); //清除所有标志位
  46. std_flash_unlock(); //关闭flash控制寄存器锁
  47. if (STD_OK != std_flash_erase(FLASH_MODE_PAGE_ERASE, (PAGE_NUM * 0x200)))return 1; //flash擦除
  48. //对齐处理
  49. if(LEN){
  50. for (word_count = 0; word_count < LEN; word_count++) {
  51. for(int i = 0; i < 4 ; i++){ //4字节合并成一个字
  52. temp1 = ((uint32_t)data[word_count*4 + i]) << (i * 8);
  53. temp |= temp1;
  54. }
  55. //写入32bit
  56. if (STD_OK != std_flash_word_program(((PAGE_NUM * 0x200) + ((word_count)*4) ), temp)) return 1;
  57. temp = 0;temp1 = 0;
  58. }
  59. if(!remainder)return 0; //刚好对齐没有尾部
  60. }
  61. //不对齐处理
  62. switch(remainder){
  63. case 1 :
  64. temp |= ((uint32_t)data[len-1]) | 0xffffff00;
  65. break;
  66. case 2 :
  67. temp1 = ((uint32_t)data[len-1]) << 8;
  68. temp1 |= ((uint32_t)data[len-2]) ;
  69. temp = temp1 | 0xffff0000;
  70. break;
  71. case 3 :
  72. temp1 = ((uint32_t)data[len-1]) << 16;
  73. temp1 |= ((uint32_t)data[len-2]) << 8;
  74. temp1 |= ((uint32_t)data[len-3]) ;
  75. temp = temp1 | 0xff000000;
  76. break;
  77. default:
  78. return 0;
  79. }
  80. if(LEN){
  81. if (STD_OK != std_flash_word_program((PAGE_NUM * 0x200)+ (LEN*4) , temp))return 1; //尾部不对齐
  82. }else{
  83. if (STD_OK != std_flash_word_program((PAGE_NUM * 0x200) , temp)) return 1; //头部不凑整
  84. }
  85. //开启flash控制寄存器锁
  86. std_flash_lock();
  87. return 0;
  88. }
  89. /*
  90. 函数:SN_FLASH_ReadE(uint8_t flash_add, uint8_t* date, uint16_t len)
  91. 功能:检查扇区是否为空
  92. 参数:物理地址 (扇区转换为物理地址: flash_add = 扇区号*512)
  93. 参数:接收数组
  94. 参数:数组长度
  95. 返回:无
  96. */
  97. void SN_FLASH_ReadE(uint32_t flash_add, uint8_t* date, uint16_t len){
  98. uint16_t word_count;
  99. for( word_count = 0; word_count < len ; word_count++){
  100. date[word_count] = *(uint8_t *)(flash_add + word_count );
  101. }
  102. }
  103. /*
  104. 函数:SN_FLASH_PAGE_null(uint8_t PAGE_NUM)
  105. 功能:检查扇区是否为空
  106. 参数:扇区号
  107. 返回:空返回 0 非空返回 1
  108. */
  109. uint8_t SN_FLASH_PAGE_null(uint8_t PAGE_NUM){
  110. uint16_t word_count = 0 ;
  111. uint16_t count = 512 >> 4;
  112. for (word_count = 0; word_count < count; word_count++)
  113. {
  114. /* 校验编程数据 */
  115. if (*(uint32_t *)(0x00000000 + (word_count << 2)) != 0xffffffff)
  116. {
  117. return 1;
  118. }
  119. }
  120. return 0;
  121. }
  122. /*
  123. 函数:SN_MUC_UID(uint32_t UID[3])
  124. 功能:检查扇区是否为空
  125. 参数:接收96位UID的数组
  126. 返回:无
  127. */
  128. void SN_MUC_UID(uint32_t UID[3]){
  129. UID[0] = *((uint32_t*)0x1FFF0340+0);
  130. UID[1] = *((uint32_t*)0x1FFF0340+1);
  131. UID[2] = *((uint32_t*)0x1FFF0340+2);
  132. }