173 lines
3.9 KiB
C
173 lines
3.9 KiB
C
#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;
|
||
}
|
||
|