#include "chipflash.h" #include "string.h" #include //H523 扇区大小为8K Byte // 算出目标地址在哪个扇区 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; // 直接写 } } // 16字节整倍数写,不支持跨扇区,扇区8KB,长度不是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; } //地址必须16字节对齐 if (ulFlashAddr & 15 ) return 1; 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 / 16; i++) { __ALIGNED(4) uint8_t FlashQuadWord[16] = {0}; memcpy( FlashQuadWord, ucpSrc, 16); ucpSrc += 16; if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, ulFlashAddr, (uint32_t)&FlashQuadWord[0]) == HAL_OK) // 双字64bit { ulFlashAddr = ulFlashAddr + 16; // 递增128bit } else { goto err; } } if (ulSize & 15) // 剩余的部分,如果不是16字节整数倍,剩余部分都是0 { __ALIGNED(4) uint8_t FlashWord[16] = {0}; memcpy(FlashWord, ucpSrc, ulSize & 15); uint32_t ptr = (uint32_t)(&FlashWord[0]); if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, ulFlashAddr, (uint32_t)(&FlashWord[0])) != HAL_OK) { goto err; } } if( HAL_FLASH_Lock() != HAL_OK) { goto err; } __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 > 0) ? (FinishSector - FirstSector) : 1; // 擦除扇区配置 EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; EraseInitStruct.Banks = FLASH_BANK_1; EraseInitStruct.Sector = FirstSector; EraseInitStruct.NbSectors = 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;