#include "chipflash.h" #include "string.h" // 算出目标地址在哪个扇区 static uint32_t bsp_get_sector(uint32_t Addr) { uint32_t sector = 0; sector = (Addr - CPU_FLASH_BASE_ADDR) / SECTOR_SIZE; return sector; } // 读取目标地址范围FLASH内容 static uint8_t bsp_read_cpu_flash(uint32_t ulFlashAddr, uint8_t *ucpDst, uint32_t ulSize) { uint32_t i; if (ulFlashAddr + ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE) { return 1; } if (ulSize == 0) // 长度为0时返回,否则起始地址为奇数地址会出错 { return 1; } for (i = 0; i < ulSize; i++) { *ucpDst++ = *(uint8_t *)ulFlashAddr++; } return 0; } // 比较FLASH 指定地址的数据是否一致 static uint8_t bsp_cmp_cpu_flash(uint32_t ulFlashAddr, uint8_t *ucpBuf, uint32_t ulSize) { uint32_t i; uint8_t ucIsEqu; // 相等标志位 uint8_t ucByte; // 如果偏移地址超过芯片容量,则不改写输出缓冲区 if (ulFlashAddr + ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE) { return FLASH_PARAM_ERR; } if (ulSize == 0) { return FLASH_IS_EQU; // FLASH内容与待写入数据相等 } ucIsEqu = 1; // 假设所有字节和待写入的数据相等,如果遇到任何一个不相等,则设置为0 for (i = 0; i < ulSize; i++) { ucByte = *(uint8_t *)ulFlashAddr; // 取1字节出来作比较 if (ucByte != *ucpBuf) // 不一致 { if (ucByte != 0xFF) // 且不等于默认 { return FLASH_REQ_ERASE; } else { ucIsEqu = 0; // 标志位置0,不一致,需要写 } } ulFlashAddr++; ucpBuf++; } if (ucIsEqu == 1) { return FLASH_IS_EQU; // 一致 } else { return FLASH_REQ_WRITE; // 直接写 } } // 8字节整倍数写,不支持跨扇区,扇区128KB,只有前64KB可靠,长度不是8字节整数倍,最后几个字节末尾补0写入 static uint8_t bsp_write_cpu_flash(uint32_t ulFlashAddr, uint8_t *ucpSrc, uint32_t ulSize) { uint32_t i; uint8_t ucRet; if (ulFlashAddr + ulSize > CPU_FLASH_BASE_ADDR + CPU_FLASH_SIZE || ulFlashAddr < CPU_FLASH_BASE_ADDR) { return 1; } if (ulSize == 0) { return 0; } ucRet = bsp_cmp_cpu_flash(ulFlashAddr, ucpSrc, ulSize); if (ucRet == FLASH_IS_EQU) { return 0; } __set_PRIMASK(1); HAL_FLASH_Unlock(); for (i = 0; i < ulSize / 8; i++) { uint64_t FlashWord = 0; memcpy((char *)&FlashWord, ucpSrc, 8); ucpSrc += 8; if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, ulFlashAddr, (uint64_t)(FlashWord)) == HAL_OK) // 双字64bit { ulFlashAddr = ulFlashAddr + 8; // 递增64bit } else { goto err; } } if (ulSize % 8) // 剩余的部分,如果不是8字节整数倍,剩余部分都是0 { uint64_t FlashWord = 0; memcpy((char *)&FlashWord, ucpSrc, ulSize % 8); if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, ulFlashAddr, (uint64_t)(FlashWord)) != HAL_OK) { goto err; } } HAL_FLASH_Lock(); __set_PRIMASK(0); return 0; err: HAL_FLASH_Lock(); __set_PRIMASK(0); return 1; } static uint8_t bsp_erase_cpu_flash(uint32_t ulFlashAddr, uint32_t u2FlashAddr) { uint32_t FirstSector = 0, NumofSectors = 0, FinishSector = 0; FLASH_EraseInitTypeDef EraseInitStruct; uint32_t SECTOR_ERR = 0; uint8_t ret; __set_PRIMASK(1); HAL_FLASH_Unlock(); // 获取此地址所在的扇区 FirstSector = bsp_get_sector(ulFlashAddr); FinishSector = bsp_get_sector(u2FlashAddr); // 固定1个扇区 NumofSectors = FinishSector - FirstSector; // 擦除扇区配置 EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Banks = FLASH_BANK_1; EraseInitStruct.PageAddress = FirstSector * SECTOR_SIZE + CPU_FLASH_BASE_ADDR; EraseInitStruct.NbPages = NumofSectors; // 扇区擦除 ret = HAL_FLASHEx_Erase(&EraseInitStruct, &SECTOR_ERR); HAL_FLASH_Lock(); __set_PRIMASK(0); return ret; } // _CHIP_INFO chip_info; // static void get_chip_info(void) // { // chip_info.ChipUniqueID[0] = *(__IO uint32_t*)(ChipUniqueID_HIGH); // chip_info.ChipUniqueID[1] = *(__IO uint32_t*)(ChipUniqueID_MEDIUM); // chip_info.ChipUniqueID[2] = *(__IO uint32_t*)(ChipUniqueID_LOW); // chip_info.ChipFlashSize = *(__IO uint16_t*)(CHIPFLASHSIZE); // chip_info.ChipMCUID = *(__IO uint32_t*)(CHIPMCUID); // } __FLASH_OPS _flash_ops = { .Read_Flash = bsp_read_cpu_flash, .Write_Flash = bsp_write_cpu_flash, .Erase_Flash = bsp_erase_cpu_flash, }; __FLASH_OPS *flash_ops = &_flash_ops;