FLASH.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #include "FLASH.h"
  2. #include "usart.h"
  3. #include "stdio.h"
  4. #include <string.h> // 包含 strlen 的头文件
  5. /*************下面所有的数都必须是4字节对齐的******************/
  6. /***************************************************************
  7. * 函数名称: Flash_GetBank
  8. * 说 明: 获得传入地址所在Bank
  9. * 参 数: faddr,Flash地址
  10. * 返 回 值: Bank值
  11. ***************************************************************/
  12. uint32_t Flash_GetBank(uint32_t faddr)
  13. {
  14. if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE_Pos) == 0)
  15. {
  16. if (faddr < (FLASH_BASE + FLASH_BANK_SIZE))
  17. return FLASH_BANK_1;
  18. else
  19. return FLASH_BANK_1;
  20. }
  21. else
  22. {
  23. if (faddr < (FLASH_BASE + FLASH_BANK_SIZE)) // bank swap
  24. return FLASH_BANK_1;
  25. else
  26. return FLASH_BANK_1;
  27. }
  28. }
  29. /***************************************************************
  30. * 函数名称: Flash_GetPage
  31. * 说 明: 获得传入地址所在Page
  32. * 参 数: faddr,Flash地址
  33. * 返 回 值: Bank值
  34. ***************************************************************/
  35. uint32_t Flash_GetPage(uint32_t faddr)
  36. {
  37. if (faddr < (FLASH_BASE + FLASH_BANK_SIZE))
  38. return (faddr - FLASH_BASE) / FLASH_PAGE_SIZE;
  39. else
  40. return (faddr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE;
  41. }
  42. /***************************************************************
  43. * 函数名称: Flash_ReadOneWord
  44. * 说 明: 从指定地址中读取一个32位的数据
  45. * 参 数: faddr,Flash地址
  46. * 返 回 值: Flash地址内的一个32位的数据
  47. ***************************************************************/
  48. uint32_t Flash_ReadOneWord(uint32_t faddr)
  49. {
  50. return *(__IO uint32_t *)faddr;
  51. }
  52. /***************************************************************
  53. * 函数名称: Flash_ErasePages
  54. * 说 明: 擦除页
  55. * 参 数: faddr,起始地址
  56. * fdataNum,要擦除的字数,实际上也是整页擦除
  57. * 返 回 值: 无
  58. ***************************************************************/
  59. void Flash_ErasePages(uint32_t faddr,uint32_t fdataNum)
  60. {
  61. if(fdataNum == 0||faddr>FLASH_ADDR_MAX)
  62. {
  63. return;
  64. }
  65. uint32_t PageError = 0;
  66. HAL_FLASH_Unlock();
  67. FLASH_EraseInitTypeDef FLASH_EraseInitSturcture;
  68. __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
  69. FLASH_EraseInitSturcture.TypeErase = FLASH_TYPEERASE_PAGES;
  70. FLASH_EraseInitSturcture.Banks = Flash_GetBank(faddr);
  71. FLASH_EraseInitSturcture.Page = Flash_GetPage(faddr);
  72. FLASH_EraseInitSturcture.NbPages = Flash_GetPage(faddr + 4 * fdataNum - 1) - FLASH_EraseInitSturcture.Page + 1;
  73. if(HAL_FLASHEx_Erase(&FLASH_EraseInitSturcture,&PageError) != HAL_OK)
  74. {
  75. HAL_FLASH_Lock();
  76. return;
  77. }
  78. }
  79. /***************************************************************
  80. * 函数名称: Flash_WriteOneWord
  81. * 说 明: 向指定地址中写入一个32位的数据
  82. * 参 数: faddr,Flash地址
  83. * fdata32,Flash地址内的一个32位的数据
  84. * 返 回 值: 写FLASH返回的状态
  85. ***************************************************************/
  86. uint8_t Flash_WriteOneWord(uint32_t faddr,uint32_t fdata32)
  87. {
  88. if(faddr<FLASH_BASE) //非法地址
  89. return HAL_ERROR;
  90. uint8_t FLASH_STATUS;
  91. uint64_t fdata64;
  92. HAL_FLASH_Unlock();
  93. if(faddr<FLASH_ADDR_MAX) //写入数据地址小于STM32L431RC的flash地址最大值
  94. {
  95. fdata64 = fdata32|0xffffffff00000000uL;
  96. FLASH_STATUS = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,faddr,fdata64);//写入数据
  97. }
  98. HAL_FLASH_Lock();
  99. return FLASH_STATUS;
  100. }
  101. /***************************************************************
  102. * 函数名称: Flash_WriteDoubleWord
  103. * 说 明: 向指定地址中写入一个双字(64位)数据
  104. * 参 数: faddr,Flash地址
  105. * fdata64,Flash地址内的一个双字(64位)数据
  106. * 返 回 值: 写FLASH返回的状态
  107. ***************************************************************/
  108. uint8_t Flash_WriteDoubleWord(uint32_t faddr,uint64_t fdata64)
  109. {
  110. if(faddr<FLASH_BASE) //非法地址
  111. return HAL_ERROR;
  112. uint8_t FLASH_STATUS;
  113. HAL_FLASH_Unlock(); //解锁FLASH
  114. if(faddr<FLASH_ADDR_MAX) //写入数据地址小于STM32L431RC的flash地址最大值
  115. {
  116. FLASH_STATUS = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,faddr,fdata64);//写入数据
  117. }
  118. HAL_FLASH_Lock(); //上锁
  119. return FLASH_STATUS;
  120. }
  121. /***************************************************************
  122. * 函数名称: Flash_Write32
  123. * 说 明: 向指定地址中写入fdataNum个32位的数据
  124. * 参 数: faddr,Flash起始地址
  125. * fdata,Flash地址内的32位的数据指针
  126. * fdata32Num,要写入的字(32位)数的数量
  127. * 返 回 值: 无
  128. ***************************************************************/
  129. void Flash_Write32(uint32_t faddr,uint32_t *fdata32, uint32_t fdata32Num)
  130. {
  131. uint64_t fdata64;
  132. HAL_FLASH_Unlock(); //解锁FLASH
  133. if(faddr<FLASH_ADDR_MAX) //写入数据地址小于STM32L431RC的flash地址最大值
  134. {
  135. for (uint32_t i = 0; i < fdata32Num / 2; i++)
  136. {
  137. fdata64 = *(uint64_t*)fdata32;
  138. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, faddr, fdata64) != HAL_OK)
  139. { //如果出现错误
  140. HAL_FLASH_Lock(); //锁定FLASH
  141. return;
  142. }
  143. faddr += 8;
  144. fdata32 += 2;
  145. }
  146. if ((fdata32Num & 0x01) == 1)
  147. {
  148. uint64_t fdata64 = *(uint64_t*)faddr;
  149. fdata64 = (fdata64 & 0xffffffff00000000uL) | (*fdata32);
  150. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, faddr, fdata64) != HAL_OK)
  151. { //如果出现错误
  152. HAL_FLASH_Lock(); //锁定FLASH
  153. return;
  154. }
  155. }
  156. }
  157. HAL_FLASH_Lock();
  158. }
  159. /***************************************************************
  160. * 函数名称: Flash_Write64
  161. * 说 明: 向指定地址中写入fdataNum个64位的数据
  162. * 参 数: faddr,Flash起始地址
  163. * fdata,Flash地址内的64位的数据指针
  164. * fdata64Num,要写入的字(64位)数的数量
  165. * 返 回 值: 无
  166. ***************************************************************/
  167. void Flash_Write64(uint32_t faddr,uint64_t *fdata64, uint32_t fdata64Num)
  168. {
  169. HAL_FLASH_Unlock(); //解锁FLASH
  170. if(faddr<FLASH_ADDR_MAX) //写入数据地址小于STM32L431RC的flash地址最大值
  171. {
  172. for (uint32_t i = 0; i < fdata64Num; i++)
  173. {
  174. if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, faddr, *fdata64) != HAL_OK)
  175. { //如果写入异常
  176. HAL_FLASH_Lock(); //上锁FLASH
  177. return;
  178. }
  179. faddr += 8;
  180. fdata64 += 1;
  181. }
  182. }
  183. HAL_FLASH_Lock(); //上锁FLASH
  184. }
  185. /***************************************************************
  186. * 函数名称: Flash_Read32
  187. * 说 明: 从指定地址开始读出指定长度的数据
  188. * 参 数: ReadAddr,起始地址
  189. * *pBuffer,数据指针
  190. * fdata32Num,字(32位)数
  191. * 返 回 值: 无
  192. ***************************************************************/
  193. void Flash_Read32(uint32_t faddr,uint32_t *fdata32,uint32_t fdata32Num)
  194. {
  195. uint32_t i;
  196. if(faddr>FLASH_ADDR_MAX) //地址小于STM32L431RC的flash地址最大值
  197. return;
  198. for(i=0;i<fdata32Num;i++)
  199. {
  200. fdata32[i] = Flash_ReadOneWord(faddr); //读取4个字节
  201. // printf("Read Flash Addr: 0x%08X, Data: 0x%08X\r\n", (unsigned int)faddr, (unsigned int)fdata32[i]);
  202. faddr+=4;
  203. }
  204. }
  205. /***************************************************************
  206. * 函数名称: FlashRead
  207. * 说 明: 从指定地址开始读出指定长度的数据
  208. * 参 数: ReadAddr,起始地址
  209. * *pBuffer,数据指针
  210. * fdata8Num,字(8位)数
  211. * 返 回 值: 无
  212. ***************************************************************/
  213. //void Flash_ReadBytes(uint32_t faddr,uint8_t *fdata8,uint32_t fdata8Num)
  214. //{
  215. // uint32_t i;
  216. // if(faddr>FLASH_ADDR_MAX) //地址小于STM32L431RC的flash地址最大值
  217. // return;
  218. // for(i=0;i<fdata8Num;i++)
  219. // {
  220. // fdata8[i] = *(__IO uint8_t *)faddr; //读取1个字节
  221. // faddr+=1;
  222. // }
  223. //}
  224. void Flash_ReadBytes(uint32_t faddr, uint8_t *fdata8, uint32_t fdata8Num) {
  225. if (faddr > FLASH_ADDR_MAX || (faddr % 4 != 0)) { // 检查地址对齐
  226. return;
  227. }
  228. uint32_t *pSrc = (uint32_t *)faddr;
  229. uint32_t *pDest = (uint32_t *)fdata8;
  230. uint32_t wordNum = (fdata8Num + 3) / 4; // 转换为32位字数
  231. for (uint32_t i = 0; i < wordNum; i++) {
  232. pDest[i] = pSrc[i]; // 按32位读取,避免字节访问异常
  233. }
  234. }
  235. /***************************************************************
  236. * 函数名称: Flash_WriteRead
  237. * 说 明: Flash数据写入、读取测试
  238. * 参 数: fAdress,flash地址
  239. * *wData,向flash地址里写入的数据
  240. * wDataLen,写入数据的长度
  241. * *rData,从flash地址里读出的数据
  242. * 返 回 值: ERROR,失败
  243. * SUCCESS,成功
  244. ***************************************************************/
  245. uint8_t Flash_WriteRead(uint32_t fAdress, uint8_t *wData, uint32_t wDataLen, uint8_t *rData)
  246. {
  247. char str_adc_vol[200];
  248. char str_read_vol[200];
  249. if (wData == NULL)
  250. {
  251. return ERROR;
  252. }
  253. uint16_t strWriteLen = (wDataLen % 4) == 0 ? (wDataLen / 4) : (wDataLen / 4 + 1);
  254. // 将 wData 转换为十六进制字符串
  255. str_adc_vol[0] = '\0';
  256. for (uint32_t i = 0; i < wDataLen; i++)
  257. {
  258. sprintf(str_adc_vol + strlen(str_adc_vol), "%02X ", wData[i]);
  259. }
  260. // printf("Flash_Write32: %s\r\n", str_adc_vol);
  261. Flash_ErasePages(fAdress, 1); // 擦除flash
  262. Flash_Write32(fAdress, (uint32_t *)wData, strWriteLen); // 写入数据
  263. Flash_ReadBytes(fAdress,rData, wDataLen); // 读出数据
  264. // 将 rData 转换为十六进制字符串
  265. str_read_vol[0] = '\0';
  266. for (uint32_t i = 0; i < wDataLen; i++)
  267. {
  268. sprintf(str_read_vol + strlen(str_read_vol), "%02X ", rData[i]);
  269. }
  270. // printf("Flash_ReadBytes: %s\r\n", str_read_vol);
  271. return SUCCESS;
  272. }
  273. void load_params_from_flash(void)
  274. {
  275. DeviceParams_t flashParams;
  276. Flash_ReadBytes(FLASH_PARAM_ADDR, (uint8_t *)&flashParams, sizeof(DeviceParams_t));
  277. if (flashParams.magic == FLASH_PARAMS_MAGIC) {
  278. g_deviceParams = flashParams;
  279. } else {
  280. // 使用默认值并保存
  281. g_deviceParams = (DeviceParams_t){
  282. .Firmware_Version = 0x0007B94F,
  283. .SlaveDevice_addr = 0x00FF,
  284. .Serial_baud_rate = 0x0002,
  285. .Device_SN = {0x00FF, 0x1906, 0x0A01},
  286. .magic = FLASH_PARAMS_MAGIC
  287. };
  288. save_params_to_flash();
  289. }
  290. }
  291. void save_params_to_flash(void)
  292. {
  293. Flash_ErasePages(FLASH_PARAM_ADDR, 1);
  294. // Flash_Write32(FLASH_PARAM_ADDR, (uint32_t *)&g_deviceParams, sizeof(DeviceParams_t) / 4 + 1);
  295. // 计算完整的32位字数(包括填充)
  296. uint32_t wordSize = (sizeof(DeviceParams_t) + 3) / 4;
  297. Flash_Write32(FLASH_PARAM_ADDR, (uint32_t *)&g_deviceParams, wordSize);
  298. }
  299. void SaveBootloaderParams(void)
  300. {
  301. Flash_ErasePages(PARAM_ADDR, sizeof(BootParams) / FLASH_PAGE_SIZE + 1);
  302. Flash_Write64(PARAM_ADDR, (uint64_t*)&params, sizeof(BootParams) / 8);
  303. }
  304. /**********************END OF FILE**********************/