flash(6058).c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* includes ----------------------------------------------------------*/
  2. #include "flash.h"
  3. /* typedef -----------------------------------------------------------*/
  4. /* define ------------------------------------------------------------*/
  5. /* macro -------------------------------------------------------------*/
  6. /* variables ---------------------------------------------------------*/
  7. param_boot s_param_boot = {
  8. .jumpAddr = 0x8040C00U,
  9. };
  10. /* function prototypes -----------------------------------------------*/
  11. /**
  12. * @brief flash读数据
  13. * @param address:读数据的起始地址
  14. read_buf:数据存储区
  15. length:读取的数据长度
  16. * @return HAL_StatusTypeDef
  17. */
  18. void FLASH_Read(uint32_t address, uint32_t *read_buf, uint32_t length)
  19. {
  20. for (uint32_t i = 0; i < length; i++)
  21. {
  22. read_buf[i] = *(volatile uint32_t*)(address + (i * 4)); // 以字(32位)为单位读取
  23. }
  24. }
  25. /**
  26. * @brief flash按页擦除
  27. * @param app_address address to jump
  28. number_of_pages:擦除页的页数
  29. * @return HAL_StatusTypeDef
  30. */
  31. HAL_StatusTypeDef FLASH_Erase(uint32_t start_address, uint32_t number_of_pages)
  32. {
  33. HAL_StatusTypeDef status = HAL_ERROR;
  34. FLASH_EraseInitTypeDef EraseInitStruct;
  35. uint32_t PageError = 0;
  36. // 解锁Flash
  37. HAL_FLASH_Unlock();
  38. // 设置擦除参数
  39. EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
  40. EraseInitStruct.PageAddress = start_address;
  41. EraseInitStruct.NbPages = number_of_pages;
  42. // 擦除Flash
  43. status = HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
  44. // 锁定Flash
  45. HAL_FLASH_Lock();
  46. return status; // 返回擦除操作的状态
  47. }
  48. /**
  49. * @brief flash按字写入
  50. * @param address:写入地址
  51. data:数据
  52. length:长度
  53. * @return HAL_StatusTypeDef
  54. */
  55. HAL_StatusTypeDef FLASH_Write(uint32_t address, uint32_t *data, uint32_t length)
  56. {
  57. HAL_StatusTypeDef status = HAL_OK;
  58. // 进入临界区 挂起所有任务
  59. vTaskSuspendAll();
  60. // 解锁Flash
  61. HAL_FLASH_Unlock();
  62. // 逐个字节写入数据
  63. for (uint32_t i = 0; i < length; i++)
  64. {
  65. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data[i]) == HAL_OK)
  66. {
  67. // 验证写入的数据
  68. if (*(uint32_t*)address != data[i])
  69. {
  70. status = HAL_ERROR;
  71. break;
  72. }
  73. address += 4; // 更新地址(一个字的大小)
  74. }
  75. else
  76. {
  77. status = HAL_ERROR;
  78. break;
  79. }
  80. }
  81. // 锁定Flash
  82. HAL_FLASH_Lock();
  83. // 退出临界区 恢复任务调度
  84. xTaskResumeAll();
  85. return status; // 返回写入操作的状态
  86. }
  87. /**
  88. * @brief 写参数区数据
  89. * @param none
  90. * @return HAL_StatusTypeDef
  91. */
  92. void Write_paramArea(uint32_t juAddr){
  93. // 擦除和写入参数
  94. uint32_t start_address = PARAM_ADDRESS; // Flash起始地址
  95. uint32_t number_of_pages = 1; // 假设我们只擦除1页
  96. param_boot *p_param_boot = &s_param_boot;
  97. // 调用擦除函数
  98. if (FLASH_Erase(start_address, number_of_pages) != HAL_OK) {
  99. // 擦除失败的处理
  100. }
  101. // 准备写入的数据
  102. p_param_boot->jumpAddr = juAddr;
  103. // 调用写入函数
  104. if (FLASH_Write(start_address, (uint32_t*)p_param_boot, sizeof(p_param_boot)) != HAL_OK) {
  105. // 写入失败的处理
  106. }
  107. }
  108. /**
  109. * @brief 参数区数据读取
  110. * @param NONE
  111. * @return HAL_StatusTypeDef
  112. */
  113. void Read_ParamArea(void) {
  114. // 读取结构体中前两个字的数据
  115. FLASH_Read(PARAM_ADDRESS, (uint32_t*)&s_param_boot, sizeof(param_boot) / sizeof(uint32_t));
  116. }
  117. /**
  118. * @brief 向量重映射
  119. * @param NONE
  120. * @return HAL_StatusTypeDef
  121. */
  122. void Remap_Vector_Table(void) {
  123. __disable_irq();
  124. Read_ParamArea();
  125. SCB->VTOR = s_param_boot.jumpAddr;
  126. __enable_irq();
  127. }