- /*Functions used for all CH32V10x devices*/
- void FLASH_SetLatency(uint32_t FLASH_Latency);
- void FLASH_HalfCycleAccessCmd(uint32_t FLASH_HalfCycleAccess);
- void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer);
- void FLASH_Unlock(void);
- void FLASH_Lock(void);
- FLASH_Status FLASH_ErasePage(uint32_t Page_Address);
- FLASH_Status FLASH_EraseAllPages(void);
- FLASH_Status FLASH_EraseOptionBytes(void);
- FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data);
- FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);
- FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);
- FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages);
- FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState);
- FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY);
- uint32_t FLASH_GetUserOptionByte(void);
- uint32_t FLASH_GetWriteProtectionOptionByte(void);
- FlagStatus FLASH_GetReadOutProtectionStatus(void);
- FlagStatus FLASH_GetPrefetchBufferStatus(void);
- void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState);
- FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG);
- void FLASH_ClearFlag(uint32_t FLASH_FLAG);
- FLASH_Status FLASH_GetStatus(void);
- FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);
- void FLASH_Unlock_Fast(void);
- void FLASH_Lock_Fast(void);
- void FLASH_BufReset(void);
- void FLASH_BufLoad(uint32_t Address, uint32_t Data0, uint32_t Data1, uint32_t Data2, uint32_t Data3);
- void FLASH_ErasePage_Fast(uint32_t Page_Address);
- void FLASH_ProgramPage_Fast(uint32_t Page_Address);
- /* New function used for all CH32V10x devices */
- void FLASH_UnlockBank1(void);
- void FLASH_LockBank1(void);
- FLASH_Status FLASH_EraseAllBank1Pages(void);
- FLASH_Status FLASH_GetBank1Status(void);
- FLASH_Status FLASH_WaitForLastBank1Operation(uint32_t Timeout);
1.1、void FLASH_SetLatency(uint32_t FLASH_Latency)
功 能:设置代码延迟值。
输 入:FLASH_Latency:指定FLASH延迟值。
1.2、void FLASH_HalfCycleAccessCmd(uint32_t FLASH_HalfCycleAccess)
功 能:启用或禁用半周期闪存访问。
输 入:FLASH_HalfCycleAccess:指定闪存半周期访问模式。
1.3、void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer)
功 能:启用或禁用预取缓冲区。
输 入:FLASH_PrefetchBuffer:指定预取缓冲区的状态。
1.4、void FLASH_Unlock(void)
功 能:解锁闪存程序擦除控制器。
输 入:无
1.5、void FLASH_UnlockBank1(void)
功 能:解锁闪存组1程序擦除控制器。
输 入:无
1.6、void FLASH_Lock(void)
功 能:锁定闪存程序擦除控制器。
输 入:无
1.7、void FLASH_LockBank1(void)
功 能:锁定闪存组1程序擦除控制器。
输 入:无
1.8、FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
功 能:擦除指定的闪存页。
输 入:Page_Address:要删除的页面地址。
1.9、FLASH_Status FLASH_EraseAllPages(void)
功 能:清除所有闪存页。
输 入:无
1.10、FLASH_Status FLASH_EraseAllBank1Pages(void)
功 能:清除所有Bank1闪存页。
输 入:无
1.11、FLASH_Status FLASH_EraseOptionBytes(void)
功 能:擦除闪存选项字节。
输 入:无
1.12、FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)
功 能:在指定的地址编程一个字。
输 入:Address:指定要编程的地址。Data:指定要编程的数据。
1.13、FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
功 能:在指定地址编程半个字。
输 入:Address:指定要编程的地址。Data:指定要编程的数据。
1.14、FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data)
功 能:在指定的选项字节数据地址编程半个字。
输 入:Address:指定要编程的地址。Data:指定要编程的数据。
1.15、FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages)
功 能:所需页面写保护。
输 入:FLASH_Pages:指定要写保护的页的地址。
1.16、FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState)
功 能:启用或禁用读取保护。
输 入:Newstate:读出保护的新状态(启用或禁用)。
1.17、FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY)
功 能:编程闪存用户选项字节:IWDG_SW/RST_STOP/RST_STDBY。
输 入:OB_IWDG:选择IWDG模式。OB_IWDG_SW:选择软件IWDG;OB_IWDG_HW:已选择硬件IWDG。
OB_STOP:进入停止模式时重置事件。OB_STOP_NoRST:进入STOP时不生成重置;OB_u STOP_RST:进入STOP时生成重置。
OB _STDBY:进入待机状态时重置事件。OB_STDBY_NoRST:进入待机状态时不生成复位;OB STDBY_RST:进入停机位时生成复位。
1.18、uint32_t FLASH_GetUserOptionByte(void)
功 能:返回闪存用户选项字节值。
输 入:无
1.19、uint32_t FLASH_GetWriteProtectionOptionByte(void)
功 能:返回闪存写入保护选项字节寄存器值。
输 入:无
1.20、FlagStatus FLASH_GetReadOutProtectionStatus(void)
功 能:检查闪存读取保护状态是否设置。
输 入:无
1.21、FlagStatus FLASH_GetPrefetchBufferStatus(void)
功 能:检查是否设置了闪存预取缓冲区状态。
输 入:无
1.22、void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState)
功 能:启用或禁用指定的闪存中断。
输 入:FLASH_IT:指定要启用或禁用的闪存中断源。NewState:指定的Flash中断的新状态(启用或禁用)。
1.23、FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG)
功 能:检查是否设置了指定的闪存标志。
输 入:FLASH_FLAG:指定要检查的FLASH标志。
1.24、void FLASH_ClearFlag(uint32_t FLASH_FLAG)
功 能:清除闪存的挂起标志。
输 入:FLASH_FLAG:指定要清除的FLASH标志。
1.25、FLASH_Status FLASH_GetStatus(void)
功 能:返回闪存状态。
输 入:无
1.26、FLASH_Status FLASH_GetBank1Status(void)
功 能:返回闪存组1状态。
输 入:无
1.27、FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout)
功 能:等待闪存操作完成或超时。
输 入:Timeout:闪存编程超时
1.28、FLASH_Status FLASH_WaitForLastBank1Operation(uint32_t Timeout)
功 能:等待Bank1上的闪存操作完成或超时。
输 入:Timeout:闪存编程超时
1.29、void FLASH_Unlock_Fast(void)
功 能:解锁快速程序擦除模式。
输 入:无
1.30、void FLASH_Lock_Fast(void)
功 能:锁定快速程序擦除模式。
输 入:无
1.31、void FLASH_BufReset(void)
功 能:闪存缓冲复位。
输 入:无
1.32、void FLASH_BufLoad(uint32_t Address, uint32_t Data0, uint32_t Data1, uint32_t Data2, uint32_t Data3)
功 能:闪存缓冲加载(128位)。
输 入:无
1.33、void FLASH_ErasePage_Fast(uint32_t Page_Address)
功 能:擦除指定的闪存页(1页=128字节)。
输 入:Page_Address:要删除的页面地址。
1.34、void FLASH_ProgramPage_Fast(uint32_t Page_Address)
功 能:编程指定的闪存页(1页=128字节)。
输 入:Page_Address:要编程的页面地址。
使用以上函数时,直接在程序中进行调用即可。
2、硬件设计
本章教程主要通过程序代码进行内部FLASH读写操作,使用CH32V103内部资源,无需进行硬件连接。
3、软件设计
CH32V103内部FLASH编程/擦除方式有两种,一种是标准编程,一种是快速编程,本章即使用上述这两种方式分别进行内部FLASH读写操作,程序编程主要分3个步骤:
1、对内部FLASH进行解锁;
2、对内部FLASH进行页擦除;
3、对内部FLASH进行读写操作。
根据上述操作步骤,编写具体程序,具体程序如下:
flash.h文件
- #ifndef __FLASH_H
- #define __FLASH_H
- #include "ch32v10x_conf.h"
- typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;
- #define PAGE_WRITE_START_ADDR ((uint32_t)0x0800F000) /* Start from 60K */
- #define PAGE_WRITE_END_ADDR ((uint32_t)0x08010000) /* End at 63K */
- #define FLASH_PAGE_SIZE 1024
- int Flash_Test(void);
- int Flash_Test_Fast(void);
- #endif
flash.h文件主要包含相关定义和函数声明;
flash.c文件
- #include "flash.h"
- /* Global Variable */
- uint32_t EraseCounter = 0x00; //记录要擦除多少页
- uint32_t Address = 0x00; //记录写入的地址
- uint16_t Data = 0xAAAA; //记录写入的数据
- uint32_t NbrOfPage; //记录写入多少页
- volatile FLASH_Status FLASHStatus = FLASH_COMPLETE; //记录每次擦除的结果
- volatile TestStatus MemoryProgramStatus = PASSED; //记录整个测试结果
- /*******************************************************************************
- * Function Name : Flash_Test
- * Description : Flash Program Test.
- * Input : None
- * Return : None
- *******************************************************************************/
- int Flash_Test(void)
- {
- FLASH_Unlock(); //解锁
- NbrOfPage = (PAGE_WRITE_END_ADDR - PAGE_WRITE_START_ADDR) / FLASH_PAGE_SIZE; //计算要擦除多少页
- //FLASH_FLAG_BSY:指示忙状态标志;FLASH_FLAG_EOP:指示操作结束标志;FLASH_FLAG_PGERR:闪存程序错误标志;FLASH_FLAG_WRPRTERR:指示写保护错误标志
- FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP|FLASH_FLAG_PGERR |FLASH_FLAG_WRPRTERR); //清空所有标志位
- for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++) //按页擦除
- {
- FLASHStatus = FLASH_ErasePage(PAGE_WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));
- }
- Address = PAGE_WRITE_START_ADDR; //向内部FLASH写入数据起始地址
- while((Address < PAGE_WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE))
- {
- FLASHStatus = FLASH_ProgramHalfWord(Address, Data); //向指定地址写入半字
- Address = Address + 2;
- }
- FLASH_Lock(); //上锁
- Address = PAGE_WRITE_START_ADDR;
- while((Address < PAGE_WRITE_END_ADDR) && (MemoryProgramStatus != FAILED))
- {
- if((*(__IO uint16_t*) Address) != Data)
- {
- MemoryProgramStatus = FAILED;
- }
- Address += 2;
- }
- return MemoryProgramStatus;
- }
- /*******************************************************************************
- * Function Name : Flash_Test_Fast
- * Description : Flash Fast Program Test.(128Byte)
- * Input : None
- * Return : None
- *******************************************************************************/
- int Flash_Test_Fast(void)
- {
- u8 i, Verity_Flag=0;
- u32 buf[32];
- for(i=0; i<32; i++)
- {
- buf[i] = i;
- }
- FLASH_Unlock_Fast(); //快速编程模式解锁
- FLASH_ErasePage_Fast(0x0800E000); //擦除指定闪存页,此处擦除0x0800E000这个地址所指定页
- printf("128Byte Page Erase Sucess\r\n");
- FLASH_BufReset(); //复位闪存缓冲区,即执行清除内部128字节缓存区操作
- FLASH_BufLoad(0x0800E000, buf[0], buf[1], buf[2], buf[3]); //向指定地址开始连续写入16字节数据(4字节/次操作,写的地址每次偏移量为4),然后执行加载到缓冲区
- FLASH_BufLoad(0x0800E000 + 0x10, buf[4], buf[5], buf[6], buf[7]);
- FLASH_BufLoad(0x0800E000 + 0x20, buf[8], buf[9], buf[10], buf[11]);
- FLASH_BufLoad(0x0800E000 + 0x30, buf[12], buf[13], buf[14], buf[15]);
- FLASH_BufLoad(0x0800E000 + 0x40, buf[16], buf[17], buf[18], buf[19]);
- FLASH_BufLoad(0x0800E000 + 0x50, buf[20], buf[21], buf[22], buf[23]);
- FLASH_BufLoad(0x0800E000 + 0x60, buf[24], buf[25], buf[26], buf[27]);
- FLASH_BufLoad(0x0800E000 + 0x70, buf[28], buf[29], buf[30], buf[31]);
- FLASH_ProgramPage_Fast(0x0800E000); //启动一次快速页编程动作,编程指定的闪存页
- printf("128Byte Page Program Sucess\r\n");
- FLASH_Lock_Fast();
- for(i=0; i<32; i++) //读编程地址数据校验
- {
- if(buf[i] == *(u32*)(0x0800E000 + 4*i))
- {
- Verity_Flag = 0;
- }
- else
- {
- Verity_Flag = 1;
- break;
- }
- }
- return Verity_Flag;
- }
flash.c文件主要包含两个函数,一个是内部FLASH标准编程函数Flash_Test,一个是内部FLASH快速编程函数Flash_Test_Fast,这两个函数具体执行过程如下:
内部FLASH标准编程函数Flash_Test执行过程:
(1)调用FLASH_Unlock函数进行解锁;
(2) 根据起始地址及结束地址计算需要擦除页数;
(3) 调用FLASH_ClearFlag函数清除各种标志位;
(4) 使用for循环以及调用FLASH_ErasePage函数擦除页数,每次擦除一页;
(5) 使用while循环并调用FLASH_ProgramWord函数向起始地址至结束地址的存储区域都写入变量“Data”存储的数值数值;
(6) 调用FLASH_Lock函数进行上锁;
(7) 使用指针读取写入的数据内容并校验。
内部FLASH快速编程函数Flash_Test_Fast执行过程与标准编程执行过程类似,具体如下:
(1)调用FLASH_Unlock_Fast函数进行解锁;
(2) 调用FLASH_ErasePage_Fast函数擦除指定闪存页;
(3) 调用FLASH_BufReset函数复位闪存缓冲区,执行清除内部128字节缓存区操作;
(4) 调用FLASH_BufLoad函数向指定地址开始连续写入16字节数据(4字节/次操作,写的地址每次偏移量为4),然后执行加载到缓冲区;
(5) 调用FLASH_ProgramPage_Fast函数启动一次快速页编程动作,编程指定的闪存页;
(6) 调用FLASH_Lock_Fast函数进行上锁;
(7) 使用for循环读取编程地址进行数据校验并返回校验值。
以上两个函数执行过程可对照CH32V103应用手册第24章闪存操作流程进行程序编写,更有助于理解编程。
main.c函数
- int main(void)
- {
- Delay_Init();
- USART_Printf_Init(115200);
- printf("SystemClk:%d\r\n",SystemCoreClock);
- printf("This is flash example\r\n");
- if(Flash_Test()== PASSED)
- {
- printf("读写内部 FLASH 标准编程测试成功\r\n");
- }
- else
- {
- printf("读写内部 FLASH 标准编程测试失败\r\n");
- }
- if(Flash_Test_Fast())
- {
- printf("128Byte Page Verity Fail,快速编程失败\r\n");
- }
- else
- {
- printf("128Byte Page Verity Sucess,快速编程成功\r\n");
- }
- while(1)
- {
- }
- }
main.c函数主要进行函数初始化以及根据flash.c文件两个函数返回值输出相应信息。
4、下载验证
将编译好的程序下载到开发板并复位,串口打印情况具体如下:
根据串口打印信息可知,内部FLASH标准编程和快速编程测试成功。