123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- #include "gd32f10x.h"
- #include "fmc.h"
- /*--------------------------------------------------*/
- /*函数名:按页擦除FLASH */
- /*参 数:start:擦除起始页 num:擦几个页 */
- /*返回值:无 */
- /*
- flash结构:
- 0x08000000~0x0807FFFF bank0(2KB一页,0~255页,共256页)共512KB
- 0x08080000~0x082FFFFF bank1(4KB一页,256~895页,共640页)共2.5MB 这个分区连续读内存需要有延时
- */
- /*-------------------------------------------------*/
- void GD32_EraseFlash(uint16_t start, uint16_t num)
- {
- uint16_t i; //用于for循环
- uint16_t j = 0;
- if ((start <= 896) && (start + num) > 896)
- {
- num = 896 - start;
- }
- else if (start > 896)
- {
- return;
- }
- fmc_unlock(); //解锁
- if ((start < 256) && ((start + num) < 256))
- {
- for(i = 0; i < num; i++) //循环num次,一个页一个页的擦除
- {
- fmc_page_erase((0x08000000 + start * 2048) + (2048 * i)); //擦除bank0一个页2KB
- }
- }
- else if ((start < 256) && ((start + num) > 256))
- {
- for(i = 0; i < num; i++) //循环num次,一个页一个页的擦除
- {
- if((start + i) < 256)
- {
- fmc_page_erase((0x08000000 + start * 2 * 1024) + (2 * 1024 * i)); //擦除bank0一个页2KB
- }
- else
- {
- fmc_page_erase(0x08080000 + (4 * 1024 * j)); //擦除bank1一个页4KB
- j++;
- }
- }
- }
- else if (start > 256)
- {
- for(i = 0; i < num; i++) //循环num次,一个页一个页的擦除
- {
- fmc_page_erase((0x08080000 + (start - 256) * 4 * 1024) + (4 * 1024 * i)); //擦除bank1一个页4KB
- }
- }
-
- fmc_lock(); //上锁
- }
- /*---------------------------------------------------------------------*/
- /*函数名:写入FLASH */
- /*参 数:saddr:写入地址 wdata:写入数据指针 wnum:写入多少个字节 */
- /*返回值:无 */
- /*---------------------------------------------------------------------*/
- void GD32_WriteFlash(uint32_t saddr, uint32_t *wdata, uint32_t wnum)
- {
- fmc_unlock(); //解锁
- while(wnum){ //循环写入,知道num等于0退出while,表示写入完毕
- fmc_word_program(saddr,*wdata); //写入一个字(4个字节)
- wnum-=4; //写入字节数量-4
- saddr+=4; //写入地址+4
- wdata++; //写入数据的指针,往后挪动一次
- }
- fmc_lock(); //上锁
- }
- // /**
- // * @brief 读取flash数据
- // *
- // * @param rbuff 接收缓冲区
- // * @param addr 起始地址,32位地址
- // * @param datalen 数据长度,多少个字节
- // */
- // void GD32_ReadFlash(uint8_t *rbuff, uint32_t addr, uint32_t datalen)
- // {
- // memcpy(rbuff,addr,datalen);
- // }
- __align(4) static uint16_t FlashBuffer[GD32FLASH_PAGE_SIZE >> 1];
- /// 初始化FLASH
- 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();
- }
- /**
- * 读FLASH
- * @param Address 地址
- * @param Buffer 存放读取的数据
- * @param Size 要读取的数据大小,单位字节
- * @return 读出成功的字节数
- */
- 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;
- }
- /**
- * 写FLASH
- * @param Address 写入起始地址,!!!要求2字节对齐!!!
- * @param Buffer 待写入的数据,!!!要求2字节对齐!!!
- * @param NumToWrite 要写入的数据量,单位:半字,!!!要求2字节对齐!!!
- * @return 实际写入的数据量,单位:字节
- */
- 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; // Address在FLASH中的偏移
- 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;
- /* 解锁FLASH */
- 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) /* FLASH擦出后默认内容全为0xFF */
- break;
- }
- if (i < pagefre)
- {
- uint32_t count = 0;
- uint32_t index = 0;
- if(FLASH_ErasePage(GD32FLASH_BASE + pagepos * GD32FLASH_PAGE_SIZE, 1) < 0)
- break;
- /* 复制到缓存 */
- for (index = 0; index < pagefre; index++)
- {
- *(FlashBuffer + pageoff + index) = *(pBuffer + index);
- }
- /* 写回FLASH */
- 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;
- }
- /* 加锁FLASH */
- fmc_lock();
- 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;
- }
|