草帽王子 发表于 2021-5-1 16:54:37

第八十九章:CH32V103应用教程——FLASH编程

本帖最后由 草帽王子 于 2021-9-10 18:24 编辑

本章主要使用CH32V103进行FLASH的擦/读/写,以及快速编程。


1、FLASH简介及相关函数介绍

关于CH2V103的FLSAH,其支持2种编程/擦除方式,具体如下:

[*]标准编程:此方式是默认编程方式(兼容方式)。这种模式下CPU以单次2字节方式执行编程,单次1K字节执行擦除及整片擦除操作。
[*]快速编程:此方式采用页操作方式(推荐)。经过特定序列解锁后,执行单次128字节的编程及128字节擦除。

关于FLASH编程,本次所用库函数中具体函数如下:
(1)FLASH_Unlock函数:此函数主要用于解锁闪存程序擦除控制器。
(2)FLASH_GetWriteProtectionOptionByte函数:此函数主要用于返回闪存写保护选项字节寄存器值。
(3)FLASH_ClearFlag函数:此函数主要用于清除闪存的挂起标志。
(4)FLASH_ErasePage函数:此函数主要用于擦除指定的闪存页。
(5)FLASH_ProgramHalfWord函数:此函数主要用于在指定的地址编写半个字的程序。
(6)FLASH_Lock函数:此函数主要用于锁定闪存程序擦除控制器。
(7)FLASH_Unlock_Fast函数:此函数主要用于解锁快速程序擦除模式。
(8)FLASH_ErasePage_Fast函数:此函数主要用于擦除指定的闪存页(1页=128字节)。
(9)FLASH_BufReset函数:此函数主要用于闪存缓冲复位。
(10)FLASH_BufLoad函数:此函数主要用于闪存缓冲区加载(128位)。
(11)FLASH_ProgramPage_Fast函数:此函数主要用于编程指定的闪存页(1页=128字节)。
(12)FLASH_Lock_Fast函数:此函数主要用于锁定快速程序擦除模式。

以上就是本次程序中所要用到的函数,关于ch32v10x_flash.c文件中的其他函数,感兴趣可对照注释以及函数内容进行了解。关于FLASH操作流程,可参考CH32V103应用手册。


2、硬件设计

本章教程主要FLASH编程操作,无需进行硬件设计。


3、软件设计

FLASH编程操作具体程序如下:
flash.h文件
#ifndef__FLASH_H
#define__FLASH_H

#include "ch32v10x_conf.h"

/* Global define */
typedef enum
{
    FAILED = 0,
    PASSED = !FAILED
} TestStatus;

#definePAGE_WRITE_START_ADDR       ((uint32_t)0x0800F000) /* Start from 60K */
//#definePAGE_WRITE_START_ADDR       ((uint32_t)0x0800E000) /* Start from 56K */

#definePAGE_WRITE_END_ADDR         ((uint32_t)0x08010000) /* End at 63K */
//#definePAGE_WRITE_END_ADDR         ((uint32_t)0x0800F000) /* End at 59K */

#defineFLASH_PAGE_SIZE             1024

//#defineFLASH_PAGES_TO_BE_PROTECTED FLASH_WRProt_Pages60to63
#defineFLASH_PAGES_TO_BE_PROTECTED FLASH_WRProt_Pages56to59

void Flash_Test(void);
void Flash_Test_Fast(void);


#endifflash.h文件主要进行相关定义和函数声明;
flash.c文件
#include "flash.h"

/* Global Variable */
uint32_t EraseCounter = 0x0, Address = 0x0;
uint16_t Data = 0xAAAA;
uint32_t WRPR_Value = 0xFFFFFFFF, ProtectedPages = 0x0;
uint32_t NbrOfPage;
volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;

volatile TestStatus MemoryProgramStatus = PASSED;
volatile TestStatus MemoryEraseStatus = PASSED;

/*******************************************************************************
* Function Name: Flash_Test
* Description    : Flash Program Test.
* Input          : None
* Return         : None
*******************************************************************************/
void Flash_Test(void)
{

//系统复位后,闪存控制器(FPEC)和 FLASH_CTLR 寄存器是被锁定的,不可访问。通过写入序列到 FLASH_KEYR 寄存器可解锁闪存控制器模块。
//解锁序列:
//1)向 FLASH_KEYR 寄存器写入 KEY1 = 0x45670123(第 1 步必须是 KEY1);
//2)向 FLASH_KEYR 寄存器写入 KEY2 = 0xCDEF89AB(第 2 步必须是 KEY2)。
//解锁闪存器
FLASH_Unlock();

//读取写保护寄存器的值1:写保护失效0:写保护有效
//每个比特位代表 4K 字节(32 页)存储写保护状态
//WPR在系统复位后从用户选择字区域加载
WRPR_Value = FLASH_GetWriteProtectionOptionByte();
printf("WRPR_Value = %x\n",WRPR_Value);

//PAGE_WRITE_START_ADDR:写入的起始地址   PAGE_WRITE_END_ADDR:结束地址   FLASH_PAGE_SIZE:一页大小,1024字节   NbrOfPage:记录要擦除的页数
NbrOfPage = (PAGE_WRITE_END_ADDR - PAGE_WRITE_START_ADDR) / FLASH_PAGE_SIZE;


if ( (WRPR_Value & FLASH_PAGES_TO_BE_PROTECTED) != 0x00)
{
    //FLASH_FLAG_BSY:指示忙状态1:表示闪存操作正在进行;0:操作结束或发生错误
    //FLASH_FLAG_EOP:指示操作结束,写1清零
    //FLASH_FLAG_PGERR:指示编程错误,写1清零
    //FLASH_FLAG_WRPRTERR:只是写保护错误,写1清零
    //清除挂起标志
    FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP|FLASH_FLAG_PGERR |FLASH_FLAG_WRPRTERR);

    //EraseCounter:擦除计数   NbrOfPage:记录要擦除的页数
    for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
    {
      //FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
      //FLASH_ErasePage:擦除指定的闪存页,此函数包含应用手册介绍主存储器标准擦除操作的2、3、4步
      FLASHStatus = FLASH_ErasePage(PAGE_WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));

      //FLASH_COMPLETE:FLASH擦除完成标志
      if(FLASHStatus != FLASH_COMPLETE)
      {
      printf("FLASH Erase ERR at Page%d\r\n",EraseCounter+60);
      }

      printf("FLASH Erase Page%d...\r\n",EraseCounter+60);
    }

    //Address:写入地址   PAGE_WRITE_START_ADDR:写入的起始地址
    Address = PAGE_WRITE_START_ADDR;

    printf("Erase Cheking...\r\n");
    while((Address < PAGE_WRITE_END_ADDR) && (MemoryEraseStatus != FAILED))
    {
      if((*(__IO uint16_t*) Address) != 0xFFFF)
      {
      MemoryEraseStatus = FAILED;
       }
      Address += 2;
    }
    if(MemoryEraseStatus == FAILED)
    {
      printf("Erase Flash FAIL!\r\n");
      printf("\r\n");
    }
    else
    {
      printf("Erase Flash PASS!\r\n");
      printf("\r\n");
    }


    Address = PAGE_WRITE_START_ADDR;
    printf("Programing...\r\n");
    while((Address < PAGE_WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE))
    {
      FLASHStatus = FLASH_ProgramHalfWord(Address, Data);
      Address = Address + 2;
      //printf("Write address:%08x\r\n",Address);
    }

    Address = PAGE_WRITE_START_ADDR;
    printf("Program Cheking...\r\n");
    while((Address < PAGE_WRITE_END_ADDR) && (MemoryProgramStatus != FAILED))
    {
      if((*(__IO uint16_t*) Address) != Data)
      {
      MemoryProgramStatus = FAILED;
       }
      Address += 2;
   }
   if(MemoryProgramStatus == FAILED)
   {
       printf("Memory Program FAIL!\r\n");
       printf("\r\n");
   }
   else
   {
       printf("Memory Program PASS!\r\n");
       printf("\r\n");
   }

   }
   else
   {
   MemoryProgramStatus = FAILED;
   printf("Error to program the flash : The desired pages are write protected\r\n");
   }

   FLASH_Lock();

}

/*******************************************************************************
* Function Name: Flash_Test_Fast
* Description    : Flash Fast Program Test.(128Byte±à³Ì)
* Input          : None
* Return         : None
*******************************************************************************/
void Flash_Test_Fast(void)
{
    u8 i, Verity_Flag=0;
    u32 buf;

    for(i=0; i<32; i++)
    {
      buf = i;
    }

    //快速变成模式解锁
    FLASH_Unlock_Fast();

    //擦除指定的闪存页
    FLASH_ErasePage_Fast(0x0800E000);

    printf("128Byte Page Erase Sucess\r\n");

    //闪存缓冲复位
    FLASH_BufReset();

    //闪存缓冲区加载(128位)。
    FLASH_BufLoad(0x0800E000, buf, buf, buf, buf);
    FLASH_BufLoad(0x0800E000 + 0x10, buf, buf, buf, buf);
    FLASH_BufLoad(0x0800E000 + 0x20, buf, buf, buf, buf);
    FLASH_BufLoad(0x0800E000 + 0x30, buf, buf, buf, buf);
    FLASH_BufLoad(0x0800E000 + 0x40, buf, buf, buf, buf);
    FLASH_BufLoad(0x0800E000 + 0x50, buf, buf, buf, buf);
    FLASH_BufLoad(0x0800E000 + 0x60, buf, buf, buf, buf);
    FLASH_BufLoad(0x0800E000 + 0x70, buf, buf, buf, buf);

    //编程指定的闪存页(1页=128字节)。
    FLASH_ProgramPage_Fast(0x0800E000);

    printf("128Byte Page Program Sucess\r\n");

    FLASH_Lock_Fast();

    for(i=0; i<32; i++)
    {
      if(buf == *(u32*)(0x0800E000 + 4*i))
      {
            Verity_Flag = 0;
      }
      else
      {
            Verity_Flag = 1;
            break;
      }
    }

    if(Verity_Flag) printf("128Byte Page Verity Fail\r\n");
    else printf("128Byte Page Verity Sucess\r\n");
}flash.c文件主要包括。关于几个函数的具体介绍,在程序中都有详细注释,在此不再赘述。
main.c文件
/********************************** (C) COPYRIGHT *******************************
* File Name          : main.c
* Author             : WCH
* Version            : V1.0.0
* Date               : 2020/04/30
* Description      : Main program body.
*******************************************************************************/

#include "debug.h"
#include "flash.h"


/* Global typedef */

/* Global define */

/* Global Variable */


/*******************************************************************************
* Function Name: main
* Description    : Main program.
* Input          : None
* Return         : None
*******************************************************************************/
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n",SystemCoreClock);
    printf("Flash Program Test\r\n");

    Flash_Test();
    Flash_Test_Fast();

    while(1)
    {
      ;
    }
}main.c文件主要进行函数初始化。


4、下载验证

将编译好的程序下载到开发版并复位,串口打印显示如下:
88、Flash编程.rar

链接:https://pan.baidu.com/s/1Ck4QHSruSouG1ypLMxkkBw
提取码:tkle
复制这段内容后打开百度网盘手机App,操作更方便哦



页: [1]
查看完整版本: 第八十九章:CH32V103应用教程——FLASH编程