GD32F103读写内部FLASH
测试环境:
- STM32F103C8
- 20KBytes RAM
- 64KBytes FLASH
头文件
#ifndef GDFLASH_H__
#define GDFLASH_H__
#include "gd32f10x.h"
#define GD32FLASH_SIZE 0X00010000UL
#define GD32FLASH_BASE FLASH_BASE
#define GD32FLASH_END (GD32FLASH_BASE | GD32FLASH_SIZE)
#define GD32FLASH_PAGE_SIZE (1024U)
#define GD32FLASH_PAGE_NUM (GD32FLASH_SIZE / GD32FLASH_PAGE_SIZE)
void FLASH_Init(void);
uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size);
uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);
int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages);
uint32_t FLASH_WriteNotErase(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite);
#endif
源文件
#include "gdflash.h"
#include <string.h>
__align(4) static uint16_t FlashBuffer[GD32FLASH_PAGE_SIZE >> 1];
void FLASH_Init(void)
{
fmc_unlock();
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
fmc_lock();
}
uint32_t FLASH_Read(uint32_t Address, void *Buffer, uint32_t Size)
{
uint32_t nread = Size;
uint8_t* d = (uint8_t *)Buffer;
const uint8_t* s = (const uint8_t *)Address;
if (!Buffer || Address < GD32FLASH_BASE || Address >= GD32FLASH_END)
return 0;
while (nread >= sizeof(uint32_t) && (((uint32_t)s) <= (GD32FLASH_END - 4)))
{
*(volatile uint32_t *)d = *(volatile uint32_t *)s;
d += sizeof(uint32_t);
s += sizeof(uint32_t);
nread -= sizeof(uint32_t);
}
while (nread && (((uint32_t)s) < GD32FLASH_END))
{
*d++ = *s++;
nread--;
}
return Size - nread;
}
uint32_t FLASH_Write(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
{
uint32_t i = 0;
uint32_t pagepos = 0;
uint32_t pageoff = 0;
uint32_t pagefre = 0;
uint32_t offset = 0;
uint32_t nwrite = NumToWrite;
const uint16_t *pBuffer = (const uint16_t *)Buffer;
if (Address < GD32FLASH_BASE || Address > (GD32FLASH_END - 2) || NumToWrite == 0 || pBuffer == NULL)
return 0;
fmc_unlock();
offset = Address - GD32FLASH_BASE;
pagepos = offset / GD32FLASH_PAGE_SIZE;
pageoff = ((offset % GD32FLASH_PAGE_SIZE) >> 1);
pagefre = ((GD32FLASH_PAGE_SIZE >> 1) - pageoff);
if (nwrite <= pagefre)
pagefre = nwrite;
while (nwrite != 0)
{
if (pagepos >= GD32FLASH_PAGE_NUM)
break;
FLASH_Read(GD32FLASH_BASE + pagepos * GD32FLASH_PAGE_SIZE, FlashBuffer, GD32FLASH_PAGE_SIZE);
for (i = 0; i < pagefre; i++)
{
if (*(FlashBuffer + pageoff + i) != 0xFFFF)
break;
}
if (i < pagefre)
{
uint32_t count = 0;
uint32_t index = 0;
if(FLASH_ErasePage(pagepos * GD32FLASH_PAGE_SIZE, 1) < 0)
break;
for (index = 0; index < pagefre; index++)
{
*(FlashBuffer + pageoff + index) = *(pBuffer + index);
}
count = FLASH_WriteNotErase(GD32FLASH_BASE + pagepos * GD32FLASH_PAGE_SIZE, FlashBuffer, GD32FLASH_PAGE_SIZE >> 1);
if (count != (GD32FLASH_PAGE_SIZE >> 1))
{
nwrite -= count;
break;
}
}
else
{
uint32_t count = FLASH_WriteNotErase(Address, pBuffer, pagefre);
if (count != pagefre)
{
nwrite -= count;
break;
}
}
pBuffer += pagefre;
Address += (pagefre << 1);
nwrite -= pagefre;
pagepos++;
pageoff = 0;
pagefre = nwrite >= (GD32FLASH_PAGE_SIZE >> 1) ? (GD32FLASH_PAGE_SIZE >> 1) : nwrite;
}
fmc_unlock();
return ((NumToWrite - nwrite) << 1);
}
uint32_t FLASH_WriteNotErase(uint32_t Address, const uint16_t *Buffer, uint32_t NumToWrite)
{
uint32_t nwrite = NumToWrite;
uint32_t addrmax = GD32FLASH_END - 2;
while (nwrite)
{
if (Address > addrmax)
break;
fmc_halfword_program(Address, *Buffer);
if ((*(__IO uint16_t*) Address) != *Buffer)
break;
nwrite--;
Buffer++;
Address += 2;
}
return (NumToWrite - nwrite);
}
int FLASH_ErasePage(uint32_t PageAddress, uint32_t NbPages)
{
while(NbPages--)
{
if(fmc_page_erase(PageAddress) != FMC_READY)
{
return -1;
}
PageAddress += GD32FLASH_PAGE_SIZE;
}
return 0;
}
ends…
|