#include "bsp_fmc_flash.h" #include #include /* 这个文件默认是根据GD32F303 实现的flash 操作接口函数,所以移植的时候,需要根据项目自行实现芯片平台相关的fmc 外设操作函数,只需要替换实现以下函数的函数体: bsp_flash_read bsp_flash_write bsp_flash_is_erased bsp_flash_erased 其他不需要动 */ #include "at32a423.h" // Device header #define BSP_FLASH_BANK_FLAGS ((fmc_flag_enum)(FMC_FLAG_PGAERR | FMC_FLAG_WPERR | \ FMC_FLAG_END | FMC_FLAG_PGERR )) #define BSP_FLASH_SN_SIZE 16U static const bsp_flash_info_t s_bsp_flash_info = { BSP_FLASH_PAGE_SIZE, BSP_FLASH_PROGRAM_UNIT, BSP_FLASH_ERASE_VALUE, }; static uint32_t bsp_flash_align_down(uint32_t value, uint32_t align) { return value & ~(align - 1U); } static uint32_t bsp_flash_align_up(uint32_t value, uint32_t align) { return (value + align - 1U) & ~(align - 1U); } static void bsp_flash_clear_flags(void) { fmc_flag_clear(BSP_FLASH_BANK_FLAGS); } static uint8_t bsp_flash_pack_word(const uint8_t *src, uint32_t size, uint32_t *word_out) { uint8_t bytes[BSP_FLASH_PROGRAM_UNIT] = { BSP_FLASH_ERASE_VALUE, BSP_FLASH_ERASE_VALUE, BSP_FLASH_ERASE_VALUE, BSP_FLASH_ERASE_VALUE }; if ((word_out == 0) || ((src == 0) && (size > 0U))) { return 0; } if (size > BSP_FLASH_PROGRAM_UNIT) { size = BSP_FLASH_PROGRAM_UNIT; } if (size > 0U) { memcpy(bytes, src, size); } *word_out = ((uint32_t)bytes[0]) | ((uint32_t)bytes[1] << 8) | ((uint32_t)bytes[2] << 16) | ((uint32_t)bytes[3] << 24); return 1; } const bsp_flash_info_t *bsp_flash_get_info(void) { return &s_bsp_flash_info; } uint8_t bsp_flash_read(uint32_t addr, void *buffer, uint32_t size) { if ((buffer == 0) && (size > 0U)) { return 0; } if (size > 0U) { memcpy(buffer, (const void *)addr, size); } return 1; } uint8_t bsp_flash_is_erased(uint32_t addr, uint32_t size) { const uint8_t *flash_ptr = (const uint8_t *)addr; uint32_t i; for (i = 0U; i < size; i++) { if (flash_ptr[i] != BSP_FLASH_ERASE_VALUE) { return 0; } } return 1; } uint8_t bsp_flash_erased(uint32_t addr, uint32_t size) { uint32_t erase_addr; uint32_t erase_end; if (size == 0U) { return 1; } erase_addr = bsp_flash_align_down(addr, BSP_FLASH_PAGE_SIZE); erase_end = bsp_flash_align_up(addr + size, BSP_FLASH_PAGE_SIZE); fmc_unlock(); bsp_flash_clear_flags(); while (erase_addr < erase_end) { if (fmc_page_erase(erase_addr) != FMC_READY) { fmc_lock(); return 0; } erase_addr += BSP_FLASH_PAGE_SIZE; bsp_flash_clear_flags(); } fmc_lock(); return 1; } uint8_t bsp_flash_write(uint32_t addr, const void *data, uint32_t size) { const uint8_t *src = (const uint8_t *)data; uint32_t offset = 0U; uint32_t word = 0U; uint32_t chunk_size; if ((addr % BSP_FLASH_PROGRAM_UNIT) != 0U) { return 0; } if ((data == 0) && (size > 0U)) { return 0; } if (size == 0U) { return 1; } fmc_unlock(); bsp_flash_clear_flags(); while (offset < size) { chunk_size = size - offset; if (chunk_size > BSP_FLASH_PROGRAM_UNIT) { chunk_size = BSP_FLASH_PROGRAM_UNIT; } if (!bsp_flash_pack_word(src + offset, chunk_size, &word)) { fmc_lock(); return 0; } if (fmc_word_program(addr + offset, word) != FMC_READY) { fmc_lock(); return 0; } offset += BSP_FLASH_PROGRAM_UNIT; bsp_flash_clear_flags(); } fmc_lock(); return 1; }