目录
一、GD32 片上flash 介绍
GD32F4xx系列微控制器可以提供高密度片上FLASH存储器,按以下分类进行组织:
1、高达3072KB主FLASH存储器。
2、高达30KB引导装载程序(boot loader)信息块存储器。
3、 高达512B OTP(一次性可编程)存储器。
4、器件配置的选项字节。
二、fmc 函数 和 操作方法
闪存控制器(FMC),提供了片上闪存需要的所有功能。MCU执行指令零等待的区域最大支持到1024K字节空间。FMC也提供了扇区擦除和整片擦除,以及32位整字或16位半字、字节编程等闪存操作。另外GD32F470xx,GD32F427xx 和 GD32F425xx系列还额外提供了页(4KB)擦除操作。
2.1 函数
gd32f4xx_fmc.h 文件中的函数声明
/* function declarations */
/* FMC main memory programming functions */
/* set the FMC wait state counter */
void fmc_wscnt_set(uint32_t wscnt);
/* unlock the main FMC operation */
void fmc_unlock(void);
/* lock the main FMC operation */
void fmc_lock(void);
/* FMC erase sector */
fmc_state_enum fmc_sector_erase(uint32_t fmc_sector);
/* FMC erase whole chip */
fmc_state_enum fmc_mass_erase(void);
/* FMC erase whole bank0 */
fmc_state_enum fmc_bank0_erase(void);
/* FMC erase whole bank1 */
fmc_state_enum fmc_bank1_erase(void);
/* FMC program a word at the corresponding address */
fmc_state_enum fmc_word_program(uint32_t address, uint32_t data);
/* FMC program a half word at the corresponding address */
fmc_state_enum fmc_halfword_program(uint32_t address, uint16_t data);
/* FMC program a byte at the corresponding address */
fmc_state_enum fmc_byte_program(uint32_t address, uint8_t data);
/* FMC option bytes programming functions */
/* unlock the option byte operation */
void ob_unlock(void);
/* lock the option byte operation */
void ob_lock(void);
/* send option byte change command */
void ob_start(void);
/* erase option byte */
void ob_erase(void);
/* enable write protect */
void ob_write_protection_enable(uint32_t ob_wp);
/* disable write protect */
void ob_write_protection_disable(uint32_t ob_wp);
/* enable erase/program protection and D-bus read protection */
void ob_drp_enable(uint32_t ob_drp);
/* disable erase/program protection and D-bus read protection */
void ob_drp_disable(uint32_t ob_drp);
/* set the option byte security protection level */
void ob_security_protection_config(uint8_t ob_spc);
/* write the FMC option byte user */
void ob_user_write(uint32_t ob_fwdgt, uint32_t ob_deepsleep, uint32_t ob_stdby);
/* option byte BOR threshold value */
void ob_user_bor_threshold(uint32_t ob_bor_th);
/* configure the boot mode */
void ob_boot_mode_config(uint32_t boot_mode);
/* get the FMC option byte user */
uint8_t ob_user_get(void);
/* get the FMC option byte write protection */
uint16_t ob_write_protection0_get(void);
/* get the FMC option byte write protection */
uint16_t ob_write_protection1_get(void);
/* get the FMC erase/program protection and D-bus read protection option bytes value */
uint16_t ob_drp0_get(void);
/* get the FMC erase/program protection and D-bus read protection option bytes value */
uint16_t ob_drp1_get(void);
/* get option byte security protection code value */
FlagStatus ob_spc_get(void);
/* get the FMC threshold value */
uint8_t ob_user_bor_threshold_get(void);
/* FMC interrupts and flags management functions */
/* enable FMC interrupt */
void fmc_interrupt_enable(uint32_t fmc_int);
/* disable FMC interrupt */
void fmc_interrupt_disable(uint32_t fmc_int);
/* get flag set or reset */
FlagStatus fmc_flag_get(uint32_t fmc_flag);
/* clear the FMC pending flag */
void fmc_flag_clear(uint32_t fmc_flag);
/* return the FMC state */
fmc_state_enum fmc_state_get(void);
/* check FMC ready or not */
fmc_state_enum fmc_ready_wait(void);
2.2 读
2.3 擦除
2.4 写
三、测试代码
3.1 相关宏定义
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */
// @defgroup FLASH_Sectors
#define FLASH_Sector_0 ((uint16_t)0x0000) /*!< Sector Number 0 */
#define FLASH_Sector_1 ((uint16_t)0x0008) /*!< Sector Number 1 */
#define FLASH_Sector_2 ((uint16_t)0x0010) /*!< Sector Number 2 */
#define FLASH_Sector_3 ((uint16_t)0x0018) /*!< Sector Number 3 */
#define FLASH_Sector_4 ((uint16_t)0x0020) /*!< Sector Number 4 */
#define FLASH_Sector_5 ((uint16_t)0x0028) /*!< Sector Number 5 */
#define FLASH_Sector_6 ((uint16_t)0x0030) /*!< Sector Number 6 */
#define FLASH_Sector_7 ((uint16_t)0x0038) /*!< Sector Number 7 */
#define FLASH_Sector_8 ((uint16_t)0x0040) /*!< Sector Number 8 */
#define FLASH_Sector_9 ((uint16_t)0x0048) /*!< Sector Number 9 */
#define FLASH_Sector_10 ((uint16_t)0x0050) /*!< Sector Number 10 */
#define FLASH_Sector_11 ((uint16_t)0x0058) /*!< Sector Number 11 */
#define FLASH_Sector_12 ((uint16_t)0x0080) /*!< Sector Number 12 */
#define FLASH_Sector_13 ((uint16_t)0x0088) /*!< Sector Number 13 */
#define FLASH_Sector_14 ((uint16_t)0x0090) /*!< Sector Number 14 */
#define FLASH_Sector_15 ((uint16_t)0x0098) /*!< Sector Number 15 */
#define FLASH_Sector_16 ((uint16_t)0x00A0) /*!< Sector Number 16 */
#define FLASH_Sector_17 ((uint16_t)0x00A8) /*!< Sector Number 17 */
#define FLASH_Sector_18 ((uint16_t)0x00B0) /*!< Sector Number 18 */
#define FLASH_Sector_19 ((uint16_t)0x00B8) /*!< Sector Number 19 */
#define FLASH_Sector_20 ((uint16_t)0x00C0) /*!< Sector Number 20 */
#define FLASH_Sector_21 ((uint16_t)0x00C8) /*!< Sector Number 21 */
#define FLASH_Sector_22 ((uint16_t)0x00D0) /*!< Sector Number 22 */
#define FLASH_Sector_23 ((uint16_t)0x00D8) /*!< Sector Number 23 */
#define GD32_FLASH_START_ADRESS ((uint32_t)0x08000000)
#define GD32_FLASH_SIZE (1024 * 1024) //512 code + 512 data
#define GD32_FLASH_END_ADDRESS ((uint32_t)(GD32_FLASH_START_ADRESS + GD32_FLASH_SIZE))
3.2 获取扇区
static uint32_t GetSector(uint32_t Address)
{
uint32_t sector = 0;
if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
{
sector = 0;
}
else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
{
sector = 1;
}
else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
{
sector = 2;
}
else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
{
sector = 3;
}
else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
{
sector = 4;
}
else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
{
sector = 5;
}
else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
{
sector = 6;
}
else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
{
sector = 7;
}
else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
{
sector = 8;
}
else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
{
sector = 9;
}
else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
{
sector = 10;
}
else if((Address < GD32_FLASH_END_ADDRESS) && (Address >= ADDR_FLASH_SECTOR_11))
{
sector = 11;
}
else
{
}
return sector;
}
3.3 读 测试代码
static int gd32_flash_read(uint32_t addr, uint8_t *buf, size_t size)
{
size_t i;
if ((addr + size) > GD32_FLASH_END_ADDRESS)
{
printf("read outrange flash size! addr is (0x%p)\r\n", (void*)(addr + size));
return -1;
}
for (i = 0; i < size; i++, buf++, addr++)
{
*buf = *(uint8_t *) addr;
printf("read flash addr is (0x%p) ,data is %d\r\n", (void*)(addr ),*buf);
}
return size;
}
3.4 擦除 测试代码
static int gd32_flash_erase(uint32_t addr, uint32_t size)
{
int result = 0;
uint32_t FirstSector = 0, NbOfSectors = 0;
if ((addr + size) > GD32_FLASH_END_ADDRESS)
{
printf("ERROR: erase outrange flash size! addr is (0x%p)\r\n", (void*)(addr + size));
return -1;
}
fmc_unlock(); //解锁flash保护
/* Get the 1st sector to erase */
FirstSector = GetSector(addr);
/* Get the number of sector to erase from 1st sector*/
NbOfSectors = GetSector(addr + size - 1) - FirstSector + 1;
fmc_flag_clear(FMC_FLAG_END);
fmc_flag_clear( FMC_FLAG_OPERR );
fmc_flag_clear(FMC_FLAG_WPERR );
fmc_flag_clear( FMC_FLAG_PGMERR );
fmc_flag_clear(FMC_FLAG_PGSERR );
fmc_flag_clear(FMC_FLAG_RDDERR);
for(int i=0;i<NbOfSectors;i++,FirstSector++)
{
if(fmc_sector_erase(CTL_SN(FirstSector))!=FMC_READY)//CTL_SN(FirstSector)
{
result = -1;
goto __exit;
}
}
__exit:
fmc_lock(); //flash上锁
if (result != 0)
{
return result;
}
printf("erase done: addr (0x%p), size %d\r\n", (void*)addr, size);
return size;
}
3.5 写 测试代码
static int gd32_flash_write(uint32_t addr, const uint8_t *buf, uint32_t size)
{
int result = 0;
uint32_t end_addr = addr + size;
if ((end_addr) > GD32_FLASH_END_ADDRESS)
{
printf("write outrange flash size! addr is (0x%p)\r\n", (void*)(addr + size));
return -1;
}
if (size < 1)
{
return -1;
}
fmc_unlock(); //解锁flash保护
fmc_flag_clear(FMC_FLAG_END);
fmc_flag_clear( FMC_FLAG_OPERR );
fmc_flag_clear(FMC_FLAG_WPERR );
fmc_flag_clear( FMC_FLAG_PGMERR );
fmc_flag_clear(FMC_FLAG_PGSERR );
fmc_flag_clear(FMC_FLAG_RDDERR);
for (uint32_t i = 0; i < size; i++, addr++, buf++)
{
/* write data to flash */
if( fmc_byte_program(addr, (uint8_t)(*buf)) == FMC_READY )
{
if (*(uint8_t *)addr != *buf)
{
result = -1;
break;
}
}
else
{
result = -1;
break;
}
}
fmc_lock(); //flash上锁
if (result != 0)
{
return result;
}
return size;
}
测试结果:
参考:
GD32F450ZGT6 手册