You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

226 lines
8.2 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. #include "zflash.h"
  2. #define ZFLASH_WRITE_DATA(start_address, data) \
  3. if (!flash_writ_32(start_address, config->ip)) { \
  4. FLASH->ACR |= 1 << 10; \
  5. HAL_FLASH_Lock();
  6. #define END() }
  7. static bool stmflash_address_legal(uint32_t start_addr, uint32_t end_addr) {
  8. if (start_addr < STM32_FLASH_BASE || start_addr % 4 || start_addr > (STM32_FLASH_BASE + STM32_FLASH_SIZE)) {
  9. return false;
  10. }
  11. if (end_addr < STM32_FLASH_BASE || end_addr % 4 || end_addr > (STM32_FLASH_BASE + STM32_FLASH_SIZE)) {
  12. return false;
  13. }
  14. return true;
  15. }
  16. static bool flash_writ_32(uint32_t *start_address, uint32_t data) {
  17. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, *start_address, data) != HAL_OK) /* 写入数据 */
  18. {
  19. return false;
  20. }
  21. *start_address += 4;
  22. return true;
  23. }
  24. /**
  25. * @brief (32)
  26. * @param faddr : (4!!)
  27. * @retval (32)
  28. */
  29. uint32_t stmflash_read_word(uint32_t faddr) { return *(volatile uint32_t *)faddr; }
  30. /**
  31. * @brief flash扇区
  32. * @param addr : lash地址
  33. * @retval 0~11,addr所在的扇区
  34. */
  35. uint8_t stmflash_get_flash_sector(uint32_t addr) {
  36. if (addr < ADDR_FLASH_SECTOR_1)
  37. return FLASH_SECTOR_0;
  38. else if (addr < ADDR_FLASH_SECTOR_2)
  39. return FLASH_SECTOR_1;
  40. else if (addr < ADDR_FLASH_SECTOR_3)
  41. return FLASH_SECTOR_2;
  42. else if (addr < ADDR_FLASH_SECTOR_4)
  43. return FLASH_SECTOR_3;
  44. else if (addr < ADDR_FLASH_SECTOR_5)
  45. return FLASH_SECTOR_4;
  46. else if (addr < ADDR_FLASH_SECTOR_6)
  47. return FLASH_SECTOR_5;
  48. else if (addr < ADDR_FLASH_SECTOR_7)
  49. return FLASH_SECTOR_6;
  50. else if (addr < ADDR_FLASH_SECTOR_8)
  51. return FLASH_SECTOR_7;
  52. else if (addr < ADDR_FLASH_SECTOR_9)
  53. return FLASH_SECTOR_8;
  54. else if (addr < ADDR_FLASH_SECTOR_10)
  55. return FLASH_SECTOR_9;
  56. else if (addr < ADDR_FLASH_SECTOR_11)
  57. return FLASH_SECTOR_10;
  58. return FLASH_SECTOR_11;
  59. }
  60. /**
  61. * @brief FLASH , ()
  62. * @note STM32F4的扇区实在太大,,0XFF
  63. * ,.0XFF的地址,.
  64. * ,,.
  65. * OTP区域也有效!OTP区!
  66. * OTP区域地址范围:0X1FFF7800~0X1FFF7A0F(16OTP数据块锁定)
  67. * @param start_address : (4!!,!)
  68. * @param pbuf :
  69. * @param length : (32)(32)
  70. * @retval
  71. */
  72. void stmflash_write(uint32_t waddr, uint32_t *pbuf, uint32_t length) {
  73. FLASH_EraseInitTypeDef flasheraseinit;
  74. HAL_StatusTypeDef FlashStatus = HAL_OK;
  75. uint32_t addrx = 0;
  76. uint32_t endaddr = 0;
  77. uint32_t sectorerror = 0;
  78. addrx = waddr; /* 写入的起始地址 */
  79. endaddr = waddr + length * 4; /* 写入的结束地址 */
  80. stmflash_address_legal(addrx, endaddr);
  81. HAL_FLASH_Unlock(); /* 解锁 */
  82. FLASH->ACR &= ~(1 << 10); /* FLASH擦除期间,必须禁止数据缓存!!! */
  83. if (addrx < 0X1FFF0000) /* 只有主存储区,才需要执行擦除操作!! */
  84. {
  85. while (addrx < endaddr) /* 扫清一切障碍.(对非FFFFFFFF的地方,先擦除) */
  86. {
  87. if (stmflash_read_word(addrx) != 0XFFFFFFFF) /* 有非0XFFFFFFFF的地方,要擦除这个扇区 */
  88. {
  89. flasheraseinit.TypeErase = FLASH_TYPEERASE_SECTORS; /* 擦除类型,扇区擦除 */
  90. flasheraseinit.Sector = stmflash_get_flash_sector(addrx); /* 要擦除的扇区 */
  91. flasheraseinit.NbSectors = 1; /* 一次只擦除一个扇区 */
  92. flasheraseinit.VoltageRange = FLASH_VOLTAGE_RANGE_3; /* 电压范围,VCC=2.7~3.6V之间!! */
  93. if (HAL_FLASHEx_Erase(&flasheraseinit, &sectorerror) != HAL_OK) {
  94. break; /* 发生错误了 */
  95. }
  96. } else {
  97. addrx += 4;
  98. }
  99. FLASH_WaitForLastOperation(FLASH_WAITETIME); /* 等待上次操作完成 */
  100. }
  101. }
  102. FlashStatus = FLASH_WaitForLastOperation(FLASH_WAITETIME); /* 等待上次操作完成 */
  103. if (FlashStatus == HAL_OK) {
  104. while (waddr < endaddr) /* 写数据 */
  105. {
  106. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, waddr, *pbuf) != HAL_OK) /* 写入数据 */
  107. {
  108. break; /* 写入异常 */
  109. }
  110. waddr += 4;
  111. pbuf++;
  112. }
  113. }
  114. FLASH->ACR |= 1 << 10; /* FLASH擦除结束,开启数据fetch */
  115. HAL_FLASH_Lock(); /* 上锁 */
  116. }
  117. /**
  118. * @brief
  119. * @param raddr :
  120. * @param pbuf :
  121. * @param length: (32),4
  122. * @retval
  123. */
  124. void stmflash_read(uint32_t raddr, uint32_t *pbuf, uint32_t length) {
  125. uint32_t i;
  126. for (i = 0; i < length; i++) {
  127. pbuf[i] = stmflash_read_word(raddr); /* 读取4个字节. */
  128. raddr += 4; /* 偏移4个字节. */
  129. }
  130. }
  131. /******************************************************************************************/
  132. /* 测试用代码 */
  133. /**
  134. * @brief (1)
  135. * @param waddr :
  136. * @param wdata :
  137. * @retval
  138. */
  139. void test_write(uint32_t waddr, uint32_t wdata) { stmflash_write(waddr, &wdata, 1); /* 写入一个字 */ }
  140. int8_t stmflash_write_config(uint32_t start_address, config_t *config, uint32_t length) {
  141. FLASH_EraseInitTypeDef flasheraseinit;
  142. HAL_StatusTypeDef FlashStatus = HAL_OK;
  143. uint32_t flash_write_start_address = 0;
  144. uint32_t flash_write_end_address = 0;
  145. uint32_t sectorerror = 0;
  146. if (start_address < STM32_FLASH_BASE ||
  147. start_address % 4 || /* 写入地址小于 STM32_FLASH_BASE, 或不是4的整数倍, 非法. */
  148. start_address >
  149. (STM32_FLASH_BASE + STM32_FLASH_SIZE)) /* 写入地址大于 STM32_FLASH_BASE + STM32_FLASH_SIZE, 非法. */
  150. {
  151. return -1;
  152. }
  153. HAL_FLASH_Unlock(); /* 解锁 */
  154. FLASH->ACR &= ~(1 << 10); /* FLASH擦除期间,必须禁止数据缓存!!! */
  155. flash_write_start_address = start_address; /* 写入的起始地址 */
  156. flash_write_end_address = start_address + length * 4; /* 写入的结束地址 */
  157. if (flash_write_start_address < 0X1FFF0000) /* 只有主存储区,才需要执行擦除操作!! */
  158. {
  159. while (flash_write_start_address < flash_write_end_address) /* 扫清一切障碍.(对非FFFFFFFF的地方,先擦除) */
  160. {
  161. if (stmflash_read_word(flash_write_start_address) != 0XFFFFFFFF) /* 有非0XFFFFFFFF的地方,要擦除这个扇区 */
  162. {
  163. flasheraseinit.TypeErase = FLASH_TYPEERASE_SECTORS; /* 擦除类型,扇区擦除 */
  164. flasheraseinit.Sector = stmflash_get_flash_sector(flash_write_start_address); /* 要擦除的扇区 */
  165. flasheraseinit.NbSectors = 1; /* 一次只擦除一个扇区 */
  166. flasheraseinit.VoltageRange = FLASH_VOLTAGE_RANGE_3; /* 电压范围,VCC=2.7~3.6V之间!! */
  167. if (HAL_FLASHEx_Erase(&flasheraseinit, &sectorerror) != HAL_OK) {
  168. break; /* 发生错误了 */
  169. }
  170. } else {
  171. flash_write_start_address += 4;
  172. }
  173. FLASH_WaitForLastOperation(FLASH_WAITETIME); /* 等待上次操作完成 */
  174. }
  175. }
  176. FlashStatus = FLASH_WaitForLastOperation(FLASH_WAITETIME); /* 等待上次操作完成 */
  177. if (FlashStatus == HAL_OK) {
  178. // ZFLASH_WRITE_DATA(&start_address, config->ip) { return -1; }
  179. // END();
  180. // ZFLASH_WRITE_DATA(&start_address, config->gw) { return -2; }
  181. // END();
  182. // ZFLASH_WRITE_DATA(&start_address, config->netmask) { return -3; }
  183. // END();
  184. // ZFLASH_WRITE_DATA(&start_address, config->localport) { return -4; }
  185. // END();
  186. // ZFLASH_WRITE_DATA(&start_address, config->obtaining_ip_mode) { return -5; }
  187. // END();
  188. }
  189. FLASH->ACR |= 1 << 10; /* FLASH擦除结束,开启数据fetch */
  190. HAL_FLASH_Lock(); /* 上锁 */
  191. return 0;
  192. }