/* ********************************************************************************************************* * IAR Development Kits * on the * * M451 * * Filename : fmc_flash.h * Version : V1.00 * Programmer(s) : Qian Xianghong ********************************************************************************************************* */ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #include "includes.h" // 读Flash全局缓冲 uint8_t Flash_rdBuf[FLASH_ERASE_SIZE]; // 写Flash缓冲 uint8_t Flash_wtBuf[FLASH_ERASE_SIZE]; // 将地址按4字节对齐 #define ALIGN_DWORD_SIZE(addr) ((addr) & 0xFFFFFFFCul) // 将地址按FLASH_ERASE_SIZE字节对齐 #define ALIGN_PAGE_SIZE(addr) ((addr) & 0xFFFFF800ul) static uint32_t GetPage(uint32_t Addr) { uint32_t page = 0; if (Addr < (FLASH_BASE + FLASH_BANK_SIZE)) { /* Bank 1 */ page = (Addr - FLASH_BASE) / FLASH_PAGE_SIZE; } else { /* Bank 2 */ page = (Addr - (FLASH_BASE + FLASH_BANK_SIZE)) / FLASH_PAGE_SIZE; } return page; } // 校验flash内容 uint8_t Flash_BufferVerify(uint32_t Addr, uint8_t *buf, uint32_t nbytes) { // 将地址按4字节对齐 uint32_t Addr4Start = ALIGN_DWORD_SIZE(Addr); uint32_t Addr4End = ALIGN_DWORD_SIZE(Addr + nbytes + 3); uint32_t u32Data, i, j = 0; for(i = Addr4Start; i < Addr4End; i += 4) { u32Data = *(__IO uint32_t *)(i); if(i >= Addr && i < Addr + nbytes && buf[j++] != (u32Data & 0xFF)) return 0; if(i + 1 >= Addr && i + 1 < Addr + nbytes && buf[j++] != ((u32Data >> 8) & 0xFF)) return 0; if(i + 2 >= Addr && i + 2 < Addr + nbytes && buf[j++] != ((u32Data >> 16) & 0xFF)) return 0; if(i + 3 >= Addr && i + 3 < Addr + nbytes && buf[j++] != (u32Data >> 24)) return 0; } return 1; } // 将flash内容读入缓冲区 void Flash_BufferRead(uint32_t Addr, uint8_t *buf, uint32_t nbytes) { // 将地址按4字节对齐 uint32_t Addr4Start = ALIGN_DWORD_SIZE(Addr); uint32_t Addr4End = ALIGN_DWORD_SIZE(Addr + nbytes + 3); uint32_t u32Data, i, j = 0; for(i = Addr4Start; i < Addr4End; i += 4) { u32Data = *(__IO uint32_t *)(i); if(i >= Addr && i < Addr + nbytes) buf[j++] = (u32Data & 0xFF); if(i + 1 >= Addr && i + 1 < Addr + nbytes) buf[j++] = ((u32Data >> 8) & 0xFF); if(i + 2 >= Addr && i + 2 < Addr + nbytes) buf[j++] = ((u32Data >> 16) & 0xFF); if(i + 3 >= Addr && i + 3 < Addr + nbytes) buf[j++] = (u32Data >> 24); } } // 擦除一页 void Flash_ErasePage(uint32_t Addr) { static FLASH_EraseInitTypeDef EraseInitStruct; uint32_t PAGEError = 0; EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Banks = FLASH_BANK_1; EraseInitStruct.Page = GetPage(ALIGN_PAGE_SIZE(Addr)); EraseInitStruct.NbPages = 1; HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError); } // 写入一页,Addr为页首地址 void Flash_PageWrite(uint32_t Addr, uint8_t *buf) { unsigned long long *buf64 = (unsigned long long *) buf; uint32_t i = Addr; while(i < Addr + FLASH_ERASE_SIZE) { HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, i, *buf64++); i += 8; } } void Flash_BufferWrite(uint32_t Addr, uint8_t *buf, uint32_t nbytes) { uint32_t count, offset; while(nbytes > 0) { // 计算页内偏移(只有第一页有可能非0) offset = Addr % FLASH_ERASE_SIZE; // 计算一页内写入字节数 count = FLASH_ERASE_SIZE - offset; if(count > nbytes) count = nbytes; // 页对齐 Addr = ALIGN_PAGE_SIZE(Addr); // 读本页内数据 Flash_BufferRead(Addr, Flash_wtBuf, FLASH_ERASE_SIZE); // 如果数据一致,不用写 if(memcmp(Flash_wtBuf + offset, buf, count) != 0) { // 擦除本页 Flash_ErasePage(Addr); // 修改数据 memcpy(Flash_wtBuf + offset, buf, count); // 写入本页数据 Flash_PageWrite(Addr, Flash_wtBuf); } // 计算下一页 Addr += FLASH_ERASE_SIZE; buf += count; nbytes -= count; } }