flash.c 3.9 KB

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