chipflash.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include "chipflash.h"
  2. #include "string.h"
  3. // 算出目标地址在哪个扇区
  4. static uint32_t bsp_get_sector(uint32_t Addr)
  5. {
  6. uint32_t sector = 0;
  7. sector = (Addr - CPU_FLASH_BASE_ADDR) / SECTOR_SIZE;
  8. return sector;
  9. }
  10. // 读取目标地址范围FLASH内容
  11. static uint8_t bsp_read_cpu_flash(uint32_t ulFlashAddr, uint8_t *ucpDst, uint32_t ulSize)
  12. {
  13. uint32_t i;
  14. if (ulFlashAddr + ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE)
  15. {
  16. return 1;
  17. }
  18. if (ulSize == 0) // 长度为0时返回,否则起始地址为奇数地址会出错
  19. {
  20. return 1;
  21. }
  22. for (i = 0; i < ulSize; i++)
  23. {
  24. *ucpDst++ = *(uint8_t *)ulFlashAddr++;
  25. }
  26. return 0;
  27. }
  28. // 比较FLASH 指定地址的数据是否一致
  29. static uint8_t bsp_cmp_cpu_flash(uint32_t ulFlashAddr, uint8_t *ucpBuf, uint32_t ulSize)
  30. {
  31. uint32_t i;
  32. uint8_t ucIsEqu; // 相等标志位
  33. uint8_t ucByte;
  34. // 如果偏移地址超过芯片容量,则不改写输出缓冲区
  35. if (ulFlashAddr + ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE)
  36. {
  37. return FLASH_PARAM_ERR;
  38. }
  39. if (ulSize == 0)
  40. {
  41. return FLASH_IS_EQU; // FLASH内容与待写入数据相等
  42. }
  43. ucIsEqu = 1; // 假设所有字节和待写入的数据相等,如果遇到任何一个不相等,则设置为0
  44. for (i = 0; i < ulSize; i++)
  45. {
  46. ucByte = *(uint8_t *)ulFlashAddr; // 取1字节出来作比较
  47. if (ucByte != *ucpBuf) // 不一致
  48. {
  49. if (ucByte != 0xFF) // 且不等于默认
  50. {
  51. return FLASH_REQ_ERASE;
  52. }
  53. else
  54. {
  55. ucIsEqu = 0; // 标志位置0,不一致,需要写
  56. }
  57. }
  58. ulFlashAddr++;
  59. ucpBuf++;
  60. }
  61. if (ucIsEqu == 1)
  62. {
  63. return FLASH_IS_EQU; // 一致
  64. }
  65. else
  66. {
  67. return FLASH_REQ_WRITE; // 直接写
  68. }
  69. }
  70. // 8字节整倍数写,不支持跨扇区,扇区128KB,只有前64KB可靠,长度不是8字节整数倍,最后几个字节末尾补0写入
  71. static uint8_t bsp_write_cpu_flash(uint32_t ulFlashAddr, uint8_t *ucpSrc, uint32_t ulSize)
  72. {
  73. uint32_t i;
  74. uint8_t ucRet;
  75. if (ulFlashAddr + ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE || ulFlashAddr < CPU_FLASH_BASE_ADDR)
  76. {
  77. return 1;
  78. }
  79. if (ulSize == 0)
  80. {
  81. return 0;
  82. }
  83. ucRet = bsp_cmp_cpu_flash(ulFlashAddr, ucpSrc, ulSize);
  84. if (ucRet == FLASH_IS_EQU)
  85. {
  86. return 0;
  87. }
  88. __set_PRIMASK(1);
  89. HAL_FLASH_Unlock();
  90. for (i = 0; i < ulSize / 8; i++)
  91. {
  92. uint64_t FlashWord = 0;
  93. memcpy((char *)&FlashWord, ucpSrc, 8);
  94. ucpSrc += 8;
  95. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, ulFlashAddr, (uint64_t)(FlashWord)) == HAL_OK) // 双字64bit
  96. {
  97. ulFlashAddr = ulFlashAddr + 8; // 递增64bit
  98. }
  99. else
  100. {
  101. goto err;
  102. }
  103. }
  104. if (ulSize % 8) // 剩余的部分,如果不是8字节整数倍,剩余部分都是0
  105. {
  106. uint64_t FlashWord = 0;
  107. memcpy((char *)&FlashWord, ucpSrc, ulSize % 8);
  108. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, ulFlashAddr, (uint64_t)(FlashWord)) != HAL_OK)
  109. {
  110. goto err;
  111. }
  112. }
  113. HAL_FLASH_Lock();
  114. __set_PRIMASK(0);
  115. return 0;
  116. err:
  117. HAL_FLASH_Lock();
  118. __set_PRIMASK(0);
  119. return 1;
  120. }
  121. static uint8_t bsp_erase_cpu_flash(uint32_t ulFlashAddr, uint32_t u2FlashAddr)
  122. {
  123. uint32_t FirstSector = 0, NumofSectors = 0, FinishSector = 0;
  124. FLASH_EraseInitTypeDef EraseInitStruct;
  125. uint32_t SECTOR_ERR = 0;
  126. uint8_t ret;
  127. __set_PRIMASK(1);
  128. HAL_FLASH_Unlock();
  129. // 获取此地址所在的扇区
  130. FirstSector = bsp_get_sector(ulFlashAddr);
  131. FinishSector = bsp_get_sector(u2FlashAddr);
  132. // 固定1个扇区
  133. NumofSectors = FinishSector - FirstSector;
  134. // 擦除扇区配置
  135. EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
  136. EraseInitStruct.Banks = FLASH_BANK_1;
  137. EraseInitStruct.PageAddress = FirstSector * SECTOR_SIZE + CPU_FLASH_BASE_ADDR;
  138. EraseInitStruct.NbPages = NumofSectors;
  139. // 扇区擦除
  140. ret = HAL_FLASHEx_Erase(&EraseInitStruct, &SECTOR_ERR);
  141. HAL_FLASH_Lock();
  142. __set_PRIMASK(0);
  143. return ret;
  144. }
  145. // _CHIP_INFO chip_info;
  146. // static void get_chip_info(void)
  147. // {
  148. // chip_info.ChipUniqueID[0] = *(__IO uint32_t*)(ChipUniqueID_HIGH);
  149. // chip_info.ChipUniqueID[1] = *(__IO uint32_t*)(ChipUniqueID_MEDIUM);
  150. // chip_info.ChipUniqueID[2] = *(__IO uint32_t*)(ChipUniqueID_LOW);
  151. // chip_info.ChipFlashSize = *(__IO uint16_t*)(CHIPFLASHSIZE);
  152. // chip_info.ChipMCUID = *(__IO uint32_t*)(CHIPMCUID);
  153. // }
  154. __FLASH_OPS _flash_ops = {
  155. .Read_Flash = bsp_read_cpu_flash,
  156. .Write_Flash = bsp_write_cpu_flash,
  157. .Erase_Flash = bsp_erase_cpu_flash,
  158. };
  159. __FLASH_OPS *flash_ops = &_flash_ops;