123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- #include "FLASH.h"
- #include "usart.h"
- #include "stdio.h"
- #include <string.h> // 包含 strlen 的头文件
- /*************下面所有的数都必须是4字节对齐的******************/
- /***************************************************************
- * 函数名称: Flash_GetBank
- * 说 明: 获得传入地址所在Bank
- * 参 数: faddr,Flash地址
- * 返 回 值: Bank值
- ***************************************************************/
- uint32_t Flash_GetBank(uint32_t faddr)
- {
- if (READ_BIT(SYSCFG->MEMRMP, SYSCFG_MEMRMP_MEM_MODE_Pos) == 0)
- {
- if (faddr < (FLASH_BASE + FLASH_BANK_SIZE))
- return FLASH_BANK_1;
- else
- return FLASH_BANK_1;
- }
- else
- {
- if (faddr < (FLASH_BASE + FLASH_BANK_SIZE)) // bank swap
- return FLASH_BANK_1;
- else
- return FLASH_BANK_1;
- }
- }
- /***************************************************************
- * 函数名称: Flash_GetPage
- * 说 明: 获得传入地址所在Page
- * 参 数: faddr,Flash地址
- * 返 回 值: Bank值
- ***************************************************************/
- uint32_t Flash_GetPage(uint32_t faddr)
- {
- if (faddr < (FLASH_BASE + FLASH_BANK_SIZE))
- return (faddr - FLASH_BASE) / FLASH_PAGE_SIZE;
- else
- return (faddr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE;
- }
- /***************************************************************
- * 函数名称: Flash_ReadOneWord
- * 说 明: 从指定地址中读取一个32位的数据
- * 参 数: faddr,Flash地址
- * 返 回 值: Flash地址内的一个32位的数据
- ***************************************************************/
- uint32_t Flash_ReadOneWord(uint32_t faddr)
- {
- return *(__IO uint32_t *)faddr;
- }
- /***************************************************************
- * 函数名称: Flash_ErasePages
- * 说 明: 擦除页
- * 参 数: faddr,起始地址
- * fdataNum,要擦除的字数,实际上也是整页擦除
- * 返 回 值: 无
- ***************************************************************/
- void Flash_ErasePages(uint32_t faddr,uint32_t fdataNum)
- {
- if(fdataNum == 0||faddr>FLASH_ADDR_MAX)
- {
- return;
- }
- uint32_t PageError = 0;
- HAL_FLASH_Unlock();
- FLASH_EraseInitTypeDef FLASH_EraseInitSturcture;
- __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
-
- FLASH_EraseInitSturcture.TypeErase = FLASH_TYPEERASE_PAGES;
- FLASH_EraseInitSturcture.Banks = Flash_GetBank(faddr);
- FLASH_EraseInitSturcture.Page = Flash_GetPage(faddr);
- FLASH_EraseInitSturcture.NbPages = Flash_GetPage(faddr + 4 * fdataNum - 1) - FLASH_EraseInitSturcture.Page + 1;
-
- if(HAL_FLASHEx_Erase(&FLASH_EraseInitSturcture,&PageError) != HAL_OK)
- {
- HAL_FLASH_Lock();
- return;
- }
- }
- /***************************************************************
- * 函数名称: Flash_WriteOneWord
- * 说 明: 向指定地址中写入一个32位的数据
- * 参 数: faddr,Flash地址
- * fdata32,Flash地址内的一个32位的数据
- * 返 回 值: 写FLASH返回的状态
- ***************************************************************/
- uint8_t Flash_WriteOneWord(uint32_t faddr,uint32_t fdata32)
- {
- if(faddr<FLASH_BASE) //非法地址
- return HAL_ERROR;
- uint8_t FLASH_STATUS;
- uint64_t fdata64;
- HAL_FLASH_Unlock();
- if(faddr<FLASH_ADDR_MAX) //写入数据地址小于STM32L431RC的flash地址最大值
- {
- fdata64 = fdata32|0xffffffff00000000uL;
- FLASH_STATUS = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,faddr,fdata64);//写入数据
- }
- HAL_FLASH_Lock();
- return FLASH_STATUS;
- }
- /***************************************************************
- * 函数名称: Flash_WriteDoubleWord
- * 说 明: 向指定地址中写入一个双字(64位)数据
- * 参 数: faddr,Flash地址
- * fdata64,Flash地址内的一个双字(64位)数据
- * 返 回 值: 写FLASH返回的状态
- ***************************************************************/
- uint8_t Flash_WriteDoubleWord(uint32_t faddr,uint64_t fdata64)
- {
- if(faddr<FLASH_BASE) //非法地址
- return HAL_ERROR;
- uint8_t FLASH_STATUS;
- HAL_FLASH_Unlock(); //解锁FLASH
- if(faddr<FLASH_ADDR_MAX) //写入数据地址小于STM32L431RC的flash地址最大值
- {
- FLASH_STATUS = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,faddr,fdata64);//写入数据
- }
- HAL_FLASH_Lock(); //上锁
- return FLASH_STATUS;
- }
- /***************************************************************
- * 函数名称: Flash_Write32
- * 说 明: 向指定地址中写入fdataNum个32位的数据
- * 参 数: faddr,Flash起始地址
- * fdata,Flash地址内的32位的数据指针
- * fdata32Num,要写入的字(32位)数的数量
- * 返 回 值: 无
- ***************************************************************/
- void Flash_Write32(uint32_t faddr,uint32_t *fdata32, uint32_t fdata32Num)
- {
- uint64_t fdata64;
- HAL_FLASH_Unlock(); //解锁FLASH
- if(faddr<FLASH_ADDR_MAX) //写入数据地址小于STM32L431RC的flash地址最大值
- {
- for (uint32_t i = 0; i < fdata32Num / 2; i++)
- {
- fdata64 = *(uint64_t*)fdata32;
- if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, faddr, fdata64) != HAL_OK)
- { //如果出现错误
- HAL_FLASH_Lock(); //锁定FLASH
- return;
- }
- faddr += 8;
- fdata32 += 2;
- }
- if ((fdata32Num & 0x01) == 1)
- {
- uint64_t fdata64 = *(uint64_t*)faddr;
- fdata64 = (fdata64 & 0xffffffff00000000uL) | (*fdata32);
- if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, faddr, fdata64) != HAL_OK)
- { //如果出现错误
- HAL_FLASH_Lock(); //锁定FLASH
- return;
- }
- }
- }
- HAL_FLASH_Lock();
- }
- /***************************************************************
- * 函数名称: Flash_Write64
- * 说 明: 向指定地址中写入fdataNum个64位的数据
- * 参 数: faddr,Flash起始地址
- * fdata,Flash地址内的64位的数据指针
- * fdata64Num,要写入的字(64位)数的数量
- * 返 回 值: 无
- ***************************************************************/
- void Flash_Write64(uint32_t faddr,uint64_t *fdata64, uint32_t fdata64Num)
- {
- HAL_FLASH_Unlock(); //解锁FLASH
- if(faddr<FLASH_ADDR_MAX) //写入数据地址小于STM32L431RC的flash地址最大值
- {
- for (uint32_t i = 0; i < fdata64Num; i++)
- {
- if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, faddr, *fdata64) != HAL_OK)
- { //如果写入异常
- HAL_FLASH_Lock(); //上锁FLASH
- return;
- }
- faddr += 8;
- fdata64 += 1;
- }
- }
- HAL_FLASH_Lock(); //上锁FLASH
- }
- /***************************************************************
- * 函数名称: Flash_Read32
- * 说 明: 从指定地址开始读出指定长度的数据
- * 参 数: ReadAddr,起始地址
- * *pBuffer,数据指针
- * fdata32Num,字(32位)数
- * 返 回 值: 无
- ***************************************************************/
- void Flash_Read32(uint32_t faddr,uint32_t *fdata32,uint32_t fdata32Num)
- {
- uint32_t i;
- if(faddr>FLASH_ADDR_MAX) //地址小于STM32L431RC的flash地址最大值
- return;
- for(i=0;i<fdata32Num;i++)
- {
- fdata32[i] = Flash_ReadOneWord(faddr); //读取4个字节
- // printf("Read Flash Addr: 0x%08X, Data: 0x%08X\r\n", (unsigned int)faddr, (unsigned int)fdata32[i]);
- faddr+=4;
- }
- }
- /***************************************************************
- * 函数名称: FlashRead
- * 说 明: 从指定地址开始读出指定长度的数据
- * 参 数: ReadAddr,起始地址
- * *pBuffer,数据指针
- * fdata8Num,字(8位)数
- * 返 回 值: 无
- ***************************************************************/
- //void Flash_ReadBytes(uint32_t faddr,uint8_t *fdata8,uint32_t fdata8Num)
- //{
- // uint32_t i;
- // if(faddr>FLASH_ADDR_MAX) //地址小于STM32L431RC的flash地址最大值
- // return;
- // for(i=0;i<fdata8Num;i++)
- // {
- // fdata8[i] = *(__IO uint8_t *)faddr; //读取1个字节
- // faddr+=1;
- // }
- //}
- void Flash_ReadBytes(uint32_t faddr, uint8_t *fdata8, uint32_t fdata8Num) {
- if (faddr > FLASH_ADDR_MAX || (faddr % 4 != 0)) { // 检查地址对齐
- return;
- }
- uint32_t *pSrc = (uint32_t *)faddr;
- uint32_t *pDest = (uint32_t *)fdata8;
- uint32_t wordNum = (fdata8Num + 3) / 4; // 转换为32位字数
-
- for (uint32_t i = 0; i < wordNum; i++) {
- pDest[i] = pSrc[i]; // 按32位读取,避免字节访问异常
- }
- }
- /***************************************************************
- * 函数名称: Flash_WriteRead
- * 说 明: Flash数据写入、读取测试
- * 参 数: fAdress,flash地址
- * *wData,向flash地址里写入的数据
- * wDataLen,写入数据的长度
- * *rData,从flash地址里读出的数据
- * 返 回 值: ERROR,失败
- * SUCCESS,成功
- ***************************************************************/
- uint8_t Flash_WriteRead(uint32_t fAdress, uint8_t *wData, uint32_t wDataLen, uint8_t *rData)
- {
- char str_adc_vol[200];
- char str_read_vol[200];
- if (wData == NULL)
- {
- return ERROR;
- }
- uint16_t strWriteLen = (wDataLen % 4) == 0 ? (wDataLen / 4) : (wDataLen / 4 + 1);
- // 将 wData 转换为十六进制字符串
- str_adc_vol[0] = '\0';
- for (uint32_t i = 0; i < wDataLen; i++)
- {
- sprintf(str_adc_vol + strlen(str_adc_vol), "%02X ", wData[i]);
- }
- // printf("Flash_Write32: %s\r\n", str_adc_vol);
- Flash_ErasePages(fAdress, 1); // 擦除flash
- Flash_Write32(fAdress, (uint32_t *)wData, strWriteLen); // 写入数据
- Flash_ReadBytes(fAdress,rData, wDataLen); // 读出数据
- // 将 rData 转换为十六进制字符串
- str_read_vol[0] = '\0';
- for (uint32_t i = 0; i < wDataLen; i++)
- {
- sprintf(str_read_vol + strlen(str_read_vol), "%02X ", rData[i]);
- }
- // printf("Flash_ReadBytes: %s\r\n", str_read_vol);
- return SUCCESS;
- }
- void load_params_from_flash(void)
- {
- DeviceParams_t flashParams;
- Flash_ReadBytes(FLASH_PARAM_ADDR, (uint8_t *)&flashParams, sizeof(DeviceParams_t));
- if (flashParams.magic == FLASH_PARAMS_MAGIC) {
- g_deviceParams = flashParams;
- } else {
- // 使用默认值并保存
- g_deviceParams = (DeviceParams_t){
- .Firmware_Version = 0x0007B94F,
- .SlaveDevice_addr = 0x00FF,
- .Serial_baud_rate = 0x0002,
- .Device_SN = {0x00FF, 0x1906, 0x0A01},
- .magic = FLASH_PARAMS_MAGIC
- };
- save_params_to_flash();
- }
- }
- void save_params_to_flash(void)
- {
- Flash_ErasePages(FLASH_PARAM_ADDR, 1);
- // Flash_Write32(FLASH_PARAM_ADDR, (uint32_t *)&g_deviceParams, sizeof(DeviceParams_t) / 4 + 1);
- // 计算完整的32位字数(包括填充)
- uint32_t wordSize = (sizeof(DeviceParams_t) + 3) / 4;
- Flash_Write32(FLASH_PARAM_ADDR, (uint32_t *)&g_deviceParams, wordSize);
- }
- void SaveBootloaderParams(void)
- {
- Flash_ErasePages(PARAM_ADDR, sizeof(BootParams) / FLASH_PAGE_SIZE + 1);
- Flash_Write64(PARAM_ADDR, (uint64_t*)¶ms, sizeof(BootParams) / 8);
- }
- /**********************END OF FILE**********************/
|