Files

173 lines
3.9 KiB
C
Raw Permalink Normal View History

2026-04-09 10:14:20 +08:00
#include "bsp_fmc_flash.h"
#include <stdio.h>
#include <string.h>
/* 这个文件默认是根据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;
}